(BOJ3665 최종 순위

Link copied to clipboard

문제 설명

Link copied to clipboard
  • 루트로부터 자식이 1개만 존재하는 트리에서, 특정 점들의 상대적 위치가 변경되었을 때, 똑같이 루트로부터 자식이 1개만 존재하는 트리가 될 수 있는지 확인하는 문제이다.
  • 모든 점들의 상대적 위치를 저장하고, 순서가 변경된 경우, 따로 저장하여 확인한다.

문제 풀이

Link copied to clipboard
N = II()
grades = list(MIIS())
M = II()
changed_grades = set(tuple(MIIS()) for _ in range(M))

teams = [[] for _ in range(N + 1)]
teams_before = [0] * (N + 1)
for i in range(N):
    for j in range(i + 1, N):
        a, b = grades[i], grades[j]
        if (a, b) in changed_grades or (b, a) in changed_grades:
            a, b = b, a
        teams[a].append(b)
        teams_before[b] += 1
  • 입력을 먼저 처리한다.
  • teams에는 더 낮은 순위의 팀들을 저장하고, teams_before에는 더 높은 순위의 팀의 수를 저장한다.
  • 모든 팀 사이 상대 순위를 저장하기 위한 for문 순회를 하고, 만약 두 팀 쌍의 순위 순서가 변경되었다면, 순서를 변경시켜 적용한다.
queue = deque([])
for i in range(1, N + 1):
    if not teams_before[i]:
        queue.append((i))
if not queue:
    print("IMPOSSIBLE")
    continue
ans = []
while queue and len(ans) < N:
    if len(queue) >= 2:
        break
    x = queue.popleft()
    ans.append(x)
    for y in teams[x]:
        teams_before[y] -= 1
        if not teams_before[y]:
            queue.append(y)
        elif teams_before[y] < 0:
            break
    else:
        continue
    break
if len(ans) == N:
    print(*ans)
else:
    print("IMPOSSIBLE")
  • 문제에서 원하는 ?가 나오는 결과는 존재하지 않을 것 같아 제외했다.
  • 먼저 가장 높은 등수의 팀을 찾고, queue에 추가한다.
    • 이 문제는 항상 한 팀만 queue에 들어 있어야 하므로 stack을 쓰거나 하나의 변수만 활용해도 문제 없을 것으로 보인다.
    • 만약 queue에 여러 개의 값이 있다면 트리가 아니게 되어 순서를 판단할 수 없다.