올해 ACM-ICPC 대전 인터넷 예선에는 총 n개의 팀이 참가했다. 팀은 1번부터 n번까지 번호가 매겨져 있다. 놀랍게도 올해 참가하는 팀은 작년에 참가했던 팀과 동일하다.
올해는 인터넷 예선 본부에서는 최종 순위를 발표하지 않기로 했다. 그 대신에 작년에 비해서 상대적인 순위가 바뀐 팀의 목록만 발표하려고 한다. (작년에는 순위를 발표했다) 예를 들어, 작년에 팀 13이 팀 6 보다 순위가 높았는데, 올해 팀 6이 팀 13보다 순위가 높다면, (6, 13)을 발표할 것이다.
창영이는 이 정보만을 가지고 올해 최종 순위를 만들어보려고 한다. 작년 순위와 상대적인 순위가 바뀐 모든 팀의 목록이 주어졌을 때, 올해 순위를 만드는 프로그램을 작성하시오. 하지만, 본부에서 발표한 정보를 가지고 확실한 올해 순위를 만들 수 없는 경우가 있을 수도 있고, 일관성이 없는 잘못된 정보일 수도 있다. 이 두 경우도 모두 찾아내야 한다.
핵심은 등수를 업데이트하는 것이다. 등수가 (a, b)로 업데이트된다고 가정하자(또한, 원래 등수는 a가 더 높다고 가정하자). 원래 a보다 뒤쳐진 인원을 n, b보다 뒤쳐진 인물을 m이라고 둔다면, a의 인원은 n-1, b의 인원은 m+1이 될 것이다.
무언가 떠올릴 수 있지 않는가? 위상 정렬 개념을 넣어 볼 수 있겠다. 즉 모든 m의 경우에 대해 위 등수를 업데이트하고, 이를 정렬한다. 만약 자기 위치와 뒤쳐진 인물의 수가 일치하지 않는다면 불가능한 경우이다. 모든 경우에 대해 앞을 만족한다면 가능한 경우이므로, 정렬된 순서를 출력하면 된다. 나 같은 경우는 원래 등수를 더 빠르게 계산하기 위해 집합을 사용해서 일일히 저장했는데, 다른 방법도 가능할 것 같다 :)
풀이 코드
import sys
input = sys.stdin.readline
def solve() :
impossible = False
unable = False
n = int(input())
t_list = list(map(int, input().split()))
orig_set = [[set(), i] for i in range(n+1)]
for i in range(n-1) :
for j in range(i+1, n) :
orig_set[t_list[i]][0].add(t_list[j])
m = int(input())
for _ in range(m) :
a, b = map(int, input().split())
if b in orig_set[a][0] : # b > a
orig_set[a][0].discard(b)
orig_set[b][0].add(a)
elif a in orig_set[b][0] : # b < a
orig_set[a][0].add(b)
orig_set[b][0].discard(a)
else :
impossible = True
orig_set.sort(key = lambda x : (-len(x[0]), -x[1]))
answer = list()
for i in range(n) :
if len(orig_set[i][0]) != n-i-1 :
impossible = True
break
answer.append(orig_set[i][1])
if not impossible :
print(*answer)
else :
print("IMPOSSIBLE")
for _ in range(int(input())) :
solve()