위상 정렬 Topological Sorting
본 글은 제 개인적인 공부를 위해 작성한 글입니다. 틀린 내용이 있다면 언제든지 피드백을 주시면 감사하겠습니다. 참고로만 활용해주시길 바랍니다.
개요
위상 정렬은 순서가 정해져 있는 작업을 차례로 수행해야 할 때 그 순서를 결정해주기 위해 사용하는 알고리즘이다.
그래프의 흐름을 조건으로 해석하자.
위상 정렬은 여러 개의 답이 존재할 수 있고, DAG(Directed Acyclic Graph)에만 적용 가능하다.
DAG = 사이클이 없는 유향 그래프
사이클이 있는 경우 왜 위상 정렬이 불가능한가?
- 위상 정렬은 시작점이 존재해야 하는데 사이클 그래프는 시작점이 없다.
위상 정렬의 결과
- 현재 그래프가 위상 정렬이 가능한가
- 위상 정렬이 가능하다면 그 결과는 무엇인가
과정
큐로 구현
- 진입 차수가 0인 노드를 큐에 삽입 (시작점)
- 큐에서 원소를 꺼내 연결된 모든 에지를 제거
- 에지 제거 이후에 진입 차수가 0이 된 노드를 큐에 삽입
- 큐가 빌 때까지 2번~3번 반복. 모든 노드를 방문하기 전에 큐가 빈다면 Cycle 존재. 모든 원소를 방문했다면 큐에서 꺼낸 순서가 위상 정렬의 결과
시간 복잡도
- $O(V+E)$
구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import sys
from collections import deque
input = sys.stdin.readline
def topology_sort(indegree, graph, n):
q = deque()
result = []
for i in range(1, n + 1):
if indegree[i] == 0:
q.append(i)
while q:
now = q.popleft()
result.append(now)
for i in graph[now]:
indegree[i] -= 1
if indegree[i] == 0:
q.append(i)
print(*result)
def main():
v, e = map(int, input().split())
indegree = [0] * (v + 1)
graph = [[] for _ in range(v + 1)]
for _ in range(e):
a, b = map(int, input().split())
graph[a].append(b)
indegree[b] += 1
topology_sort(indegree, graph, v)
if __name__ == "__main__":
main()
'''
INPUT
4 5
1 2
1 3
2 3
2 4
3 4
ANS
1 2 3 4
'''
참고
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.