알고리즘/BAEKJOON (Python)

[ 백준 ][ 골드2 ] 1766번 - 문제집 ( 파이썬 )

Heeto 2023. 2. 27. 13:18
링크 : https://www.acmicpc.net/problem/1766
 

1766번: 문제집

첫째 줄에 문제의 수 N(1 ≤ N ≤ 32,000)과 먼저 푸는 것이 좋은 문제에 대한 정보의 개수 M(1 ≤ M ≤ 100,000)이 주어진다. 둘째 줄부터 M개의 줄에 걸쳐 두 정수의 순서쌍 A,B가 빈칸을 사이에 두고 주

www.acmicpc.net

 

문제


코드


import heapq
import sys
input = sys.stdin.readline

n,m = map(int,input().split())

first = [[] for _ in range(n+1)]
link = [0 for _ in range(n+1)]

for _ in range(m):
    a,b = map(int,input().split())
    first[a].append(b)
    link[b] += 1

hq = []
for i in range(1,n+1):
    if link[i] == 0:
        heapq.heappush(hq,i)
while hq:
    node = heapq.heappop(hq)
    print(node,end = " ")
    for x in first[node]:
        link[x] -= 1
        if link[x] == 0:
            heapq.heappush(hq,x)

 

풀이


대표적인 위상정렬에 작은 변화를 준 변형문제이다.

 

내가 생각하는 위상정렬은 다음과 같다.

다른 참고자료 없이 내 생각 그대로 적었기 때문에 오류가 있을 수는 있다.

어떤 노드를 방문하기 전 반드시 방문해야 하는 선순위 노드가 있을 때, 선순위 노드를 방문처리하며 후순위 노드들의 값을 갱신해가며 먼저 방문해야 할 노드들이 사라진 노드들을 다시 방문하는 방법

이 문제에서 추가로 요구하는 조건은 '가능하면 쉬운 문제부터 풀어야 한다' 이다.

가능하면 쉬운 문제라는 것은 문제에서 번호가 낮은 순이기 때문에 3번 조건을 해결하기 위해서 우선순위 큐를 사용했다.

 

| 위상정렬 + 우선순위큐 |

  • 선순위 노드를 인덱스로 두고 후순위 노드들을 저장하는 배열 first와 선순위 노드의 개수들을 저장한 link배열을 만든다.
  • 정보들을 모두 배열에 넣는다.
  • link배열을 탐색하면서 선순위 노드가 없는 노드들을 우선순위큐에 넣는다.
  • 우선순위큐에 넣으면 모두 선순위 노드가 없는 노드들 중 가장 작은 수가 먼저 나오기 때문에 3번 조건이 만족된다.
  • 우선순위 큐에서 노드를 꺼낼 때마다 그 노드를 선순위로 하는 모든 노드의 link값을 줄이고 0이 되면 다시 우선순위 큐에 넣어준다.