크래프톤 정글
크래프톤 정글 8기 - 15일차 TIL
고웅
2025. 3. 25. 11:08
TIL - 2025.03.25 (화요일)
📝 오늘 배운 것 (위상정렬 알고리즘 (Topology Sort))
위상 정렬 (Topology Sort)
- DAG에서 정점을 나열하는 알고리즘
- DAG란?
- Directed Acyclic Graph
- 방향이 있고, 사이클이 없는 그래프
- 노드 간 선 후 관계를 나타내기 위해 사용한다.
- ex) 작업 공정, 스케줄링
- B 작업은 A작업이 선행되어야 진행할 수 있다.
- 사이클이 존재하는 그래프는 위상 정렬을 할 수 없다.
구현 방법
- 진입 차수가 0인 정점 선택
- 선택된 정점을 위상 정렬된 대상으로 출력
- 해당 정점과 연결된 간선을 제거 (진입 차수를 감소)
- 모든 노드를 다 정렬할 때까지 1 ~ 3을 반복
시간 복잡도
모든 노드를 확인하며 해당 노드와 연결된 간선을 제거해야 하므로 시간 복잡도 O(V+E)가 된다.
💡 문제 해결
예시 문제
import sys
from collections import deque
input = sys.stdin.readline
n, m = map(int, input().split())
indegree = [0] * (n+1)
graph = [[] for _ in range(n+1)]
for _ in range(m):
a, b = map(int, input().split())
graph[a].append(b)
indegree[b] += 1
answer = [1] * (n+1)
def topology_sort():
result = []
q = deque()
for i in range(1,n+1):
if indegree[i] == 0:
q.append(i)
answer[i] = 1
for i in range(1, n+1):
now = q.popleft()
result.append(now)
for next in graph[now]:
indegree[next] -= 1
if indegree[next] == 0:
q.append(next)
answer[next] = answer[now] + 1
print(*answer[1:])
topology_sort()
위상 정렬을 2개의 배열을 만드는데 하나는 2중 배열이다. 이 배열에는 인덱스 값에 해당 노드와 연결된 다른 노드의 번호를 기록해 두고
다른 하나의 배열 indegree에는 해당 노드와 연결된 다른 노드에 진입 차수를 1 늘리는 것이다.
for _ in range(m):
a, b = map(int, input().split())
graph[a].append(b)
indegree[b] += 1
다음으로 indegree 배열 즉 진입 차수와 관련된 배열을 돌면서 진입차수가 0인 즉 시작 점을 큐에 넣게 된다.
q = deque()
for i in range(1,n+1):
if indegree[i] == 0:
q.append(i)
answer[i] = 1
시작점은 큐에 넣은 후 다시 반복하며 큐에 담긴 노드 정보를 빼내 며 해당 노드가 진출하는 노드들을 방문하고 방문한 노드의 indegree 값을 1 감소시킨다. 이후 방문한 노드가 진입 차수가 0이 되면 해당 노드를 다시 큐에 넣으며 순차적인 경로를 기록한다.
🔍 더 알아볼 것
위상정렬 관련 문제
ACM Craft - 백준 1005번 풀어보기
줄 세우기 - 백준 2252번 풀어보기