위상정렬 (Topology Sort)
Updated:
위상 정렬 이해
위상정렬은 유향 그래프(DAG)에서 각 정점들의 선행 순서를 위배하지 않으면서 나열하는 것이다.
예를들면, 스타크래프트에서 스포닝 풀을 짓고 히드라 덴을 지을 수 있듯이 순서를 지키면서 정렬하는 알고리즘이다.
위상정렬에 사용되는 배열을 degree(진입 차수)라 한다. 이 배열은 어떤 정점이 호출된 수를 저장해 놓은 것인데 진입 차수가 0이라는 것은 현재 정점을 탐색할 수 있음을 나타낸다.
위상 정렬 구현
#include <iostream>
#include <queue>
using namespace std;
int main() {
int n; // 정점의 개수
vector<int> graph[n+1]; // (x -> graph[x][0])
vector<int> degree(n+1,0);
for(int i=1;i<=n;i++) { // 호출되는 정점의 차수를 증가
for(int j=0;j<graph[i].size();j++) {
int v=graph[i][j];
degree[v]++;
}
}
// topology sort
queue<int> q;
for(int i=1;i<=n;i++) { // 진입 차수가 0인 정점을 큐에 삽입
if(degree[i]==0) q.push(i);
}
vector<int> ret; // 정렬순서를 저장할 배열
for(int i=1;i<=n;i++) {
if(q.empty()) {
// n개를 방문하기 전에 큐가 비어버리면 사이클이 존재
cout<<"cycle detected"<<endl;
return 0;
}
int x=q.front();
q.pop();
ret.push_back(x);
for(int j=0;j<graph[x].size();j++) {
int v=graph[x][j];
if(--degree[v]==0) q.push(v);
}
}
// ret 출력
for(auto it : ret) cout<<it<<' ';
return 0;
}
위상 정렬 성능
위상정렬은 정점의 개수 $V$ + 간선의 개수 $E$ 번을 탐색하므로 $O(V+E)$의 시간 복잡도를 가진다.
Comments