daniel7481의 개발일지

[BOJ] 17616 등수 찾기 본문

BOJ

[BOJ] 17616 등수 찾기

daniel7481 2021. 12. 17. 17:22
반응형

https://www.acmicpc.net/problem/17616

 

17616번: 등수 찾기

표준 입력으로 다음 정보가 주어진다. 첫 번째 줄에 세 정수 N, M, X가 공백을 사이에 두고 주어진다. (2 ≤ N ≤ 105, 1 ≤ M ≤ min(N(N-1)/2, 5×105), 1 ≤ X ≤ N) . 다음 M 줄에는 각각 두 정수 A, B가 주어

www.acmicpc.net

문제

KOI 본선 대회에 N명의 학생이 참가했다. 이 학생들을 각각 1부터 N까지 정수로 표현하자. 대회가 끝나고 성적을 발표하는데, 이 대회는 전체 학생의 등수를 발표 하는 대신, 두 학생 A, B가 대회 본부에 찾아가면 본부는 두 학생 중 어느 학생이 더 잘 했는지를 알려준다. 둘 이상의 학생이 동점인 경우는 없다.

자신의 전체에서 등수가 궁금한 학생들은 둘 씩 짝을 지어서 대회 본부에 총 M번 질문을 했다. 여러분은 등수를 알고 싶은 학생 X와 대회 본부의 질문에 대한 답들 로부터 이 학생 X의 등수 범위를 찾아서 출력한다. 질문에 대한 답으로 알 수 있는 최대한 정확한 답을 출력한다.

입력

표준 입력으로 다음 정보가 주어진다. 첫 번째 줄에 세 정수 N, M, X가 공백을 사이에 두고 주어진다. (2 ≤ N ≤ 105, 1 ≤ M ≤ min(N(N-1)/2, 5×105), 1 ≤ X ≤ N) . 다음 M 줄에는 각각 두 정수 A, B가 주어지는데, 이 뜻은 학생 A가 학생 B보다 더 잘했다는 뜻이다. 같은 A, B가 둘 이상의 줄에 주어지는 경우는 없고, 입력된 값이 정확함이 보장된다.

출력

표준 출력으로 두 정수 U, V (1 ≤ U ≤ V ≤ N)를 출력한다. 이는 학생 X의 가능한 가장 높은 등수가 U, 가능한 가장 낮은 등수가 V임을 나타낸다. 만약 학생 X의 가능한 등수가 정확하게 하나라면, U = V이다.

서브태스크

번호배점제한
1 12 N ≤ 10
2 11 N ≤ 1,000, M = N(N-1)/2
3 34 N ≤ 1,000
4 43 원래의 제약조건 이외에 아무 제약조건이 없다.

풀이

서브 태스크 문제는 all or nothing이기 때문에 항상 떨린다. 이 문제는 처음에는 위상정렬을 활용할까 생각했는데, 곧 학생들간에 순위는 트리 구조가 아니므로 그냥 bfs를 사용하기로 하였다. 제일 높은 순위와 제일 낮은 순위를 구해야하는데, 가장 높은 순위는 위에 몇명이 있는지를 구하면 가장 높은 순위를 구할 수 있고, 가장 낮은 순위는 자기 밑에 몇명이 있는지만 구하면 구할 수 있었다. 메모리 낭비가 좀 심할수도 있지만 두 학생의 관계가 주어졌을 때, 자기보다 높은 학생들을 구하는 up 배열과 낮은 학생을 구하는 down배열을 선언한 후 넣어주었다. 그 다음 두 가지 경우에 대하여 bfs를 돌아주었는데, 새로운 인물이 나올 때마다 up_people과 down_people에 하나씩 더해줌으로써 자기보다 위에 있는 사람과 자기보다 아래에 있는 사람들의 수를 구하였다. 그 후에 순위는 1등부터 있으므로 up_people+1을 출력. n-down_people을 출력하였다.

import sys
from collections import deque
n, m, x = map(int, input().split()) #사람 수, 관계의 수, 순위를 구하려는 사람
up = [[]for _ in range(n+1)] #자기보다 높은 사람들
down = [[]for _ in range(n+1)] #자기보다 낮은 사람들
for _ in range(m):
  p1, p2 = map(int, input().split())
  up[p2].append(p1)#자기보다 높은 사람을 요소로 삽입
  down[p1].append(p2)#자기보다 낮은 사람을 요소로 삽입
q = deque()
visited = [False for _ in range(n+1)]
q.append(x)
up_people = 0
while q:
  v = q.popleft()
  for a in up[v]:
    if not visited[a]:
      q.append(a)
      up_people += 1 #x보다 순위가 높은 사람들의 수
      visited[a] = True
q = deque()
visited = [False for _ in range(n+1)]
q.append(x)
down_people = 0
while q:
  v = q.popleft()
  for a in down[v]:
    if not visited[a]:
      q.append(a)
      down_people += 1 #x보다 순위가 낮은 사람들의 수
      visited[a] = True
print(up_people+1, end = ' ')
print(n-down_people)
반응형

'BOJ' 카테고리의 다른 글

[BOJ] 19236 청소년 상어  (0) 2021.12.24
[BOJ] 17140 이차원 배열과 연산  (0) 2021.12.24
[BOJ] 2193 이친수  (0) 2021.12.16
[BOJ] 10844 쉬운 계단 수  (0) 2021.12.16
[BOJ] 17135 캐슬 디펜스  (0) 2021.12.16