위상정렬은 정렬 알고리즘의 일종이다. 이는 순서가 정해져 있는 일련의 작업을 차례대로 수행해야 할 때 사용할 수 있는 알고리즘이다. 조금더 구체적으로 위상 정렬은 방향 그래프의 모든 노드를 방향성에 거스르지 않도록 순서대로 나열하는 것이다. 예시로는 선수과목이 있다. 자료구조 과목을 수강한뒤에 알고리즘 과목을 수강하는 것이 권장된다면, 위상 정렬을 수행하여 모든 선후 관계를 지키는 전체 순서를 게산할 수 있다. 구체적인 동작 과정을 아래와 같다.
- 진입 차수가 0인 노드를 큐에 넣는다.
- 큐가 빌 때까지 다음의 과정을 반복한다.
- 큐에서 원소를 꺼내 해당 노드에서 출발하는 간선을 그래프에서 제거한다.
- 새롭게 진입차수가 0이 된 노드를 큐에 넣는다.
위상 정렬 알고리즘은 큐가 빌때까지 큐에서 원소를 꺼내고 처리하는 과정을 반복한다. 이때 모든 원소를 방문하기 전에 큐가 빈다면 사이클이 존재한다고 판단할 수 있다.
from collections import deque
#노드의 개수와 간선(union 연산)의 개수 입력 받기
v, e = map(int, input().split())
#모든 노드에 대한 진입차수는 0으로 초기화
indegree = [0] * (v + 1)
#그래프 초기화
graph = [[] for _ in range(v + 1)]
#모든 간선 정보 입력받기
for i in range(e):
a, b = map(int, input().split())
graph[a].append(b) #정점 a 에서 b로 이동 가능
indegree[b] += 1
def topology_sort():
result = [] #알고리즘 수행 결과를 담을 리스트
q = deque()
#처음 시작할 때 진입차수가 0인 노드를 삽입
for i in range(1, v + 1):
if indegree[i] == 0:
q.append(i)
while q:
now = q.popleft()
result.append(now)
for i in graph[now]:
indegree[i] -= 1
#새롭게 진입차수가 0이 되는 노드를 큐에 삽입
if indegree[i] == 0:
q.append(i)
#위상 정렬을 수행한 결과 출력
for i in result:
print(i, end=' ')
topology_sort()