위상정렬
by
위상정렬
위상정렬은 어떤 일이 선/후 관계가 정해져있을 때 이용가능한 알고리즘이다.
대표적으로 “선수과목”, “업무순서배치” 등에서 사용된다.
이 정렬은 DAG
에서만 가능하다.
DAG
: 사이클이 없는 방향 그래프
방식
- DFS 역순
- indegeree(진입차수)
DFS방식
방법
-
DFS를 실행하면서 DFS가 끝나는 순서대로 Stack에 삽입한다.
-
stack의 top을 차례대로 추출한다.
#include<cstdio>
#include <stdio.h>
#include<stack>
using namespace std;
vector<vector<int>> vt;
stack<int> st;
int n, m, x, y, visited[32001],finish[32001],cycle;
void dfs(int v) {
visited[v] = true;
for (auto i : vt[v]) {
if (visited[i])
continue;
dfs(i);
}
st.push(v);
}
int main() {
scanf_s("%d%d", &n, &m);
vt.resize(n + 1);
for (int i = 0; i < m; i++) {
scanf_s("%d%d", &x, &y);
vt[x].push_back(y);
}
for (int i = 1; i <= n; i++) {
if (!visited[i])
dfs(i);
}
while (st.size()) {
printf("%d ", st.top());
st.pop();
}
```
return 0;
```
}
위상정렬은 DAG에서만 가능하므로 Cycle의 여부를 확인할 필요가 있다.
cycle 확인 방법
/* cycle여부판단하는 코드 추가
void dfs(int here)
{
visited[here] = true;
for (auto there : vt[here])
{
if (!visited[there])
dfs(there);
else if (!finish[there]) //visit되어있는데 아직 끝나지 않은 정점을 dfs호출도중 보게 되면 역방향 간선
cycle = 1;
}
finish[here] = true;
st.push(here);
}
*/
Indegree방식
indegree란 한 정점에서 자신에게 들어오는 방향인 간선의 수
예시
1번 정점 : 0
2번 정점 : 1
3번 정점 : 0
4번 정점 : 3
방법
(큐가 빌때까지 반복)
- 모든 정점의 indegree의 개수를 세준 후 queue에 indegree가 0인 정점을 삽입
- 큐에서 노드를 추출(indegree가 0이면 정렬이 완료)
- 뽑은 노드와 연결된 노드의 진입차수들을 -1
-
- 사용하는자료구조
-
큐를 사용하지만 min heap을 사용하면 동시에 여러 원소가 있을 때 큐가 작은 원소를 먼저 내보낸다!
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
int n, m, a, b, in[32001];
vector<vector<int>> vt;
priority_queue<int> pq;
int main() {
scanf_s("%d%d", &n, &m);
vt.resize(n + 1);
for (int i = 0; i < m; i++) {
scanf_s("%d%d", &a, &b);
vt[a].push_back(b);
in[b]++;
}
for (int i = 1; i <= n; i++)
{
if (in[i] == 0)
pq.push(-i);
}
while (pq.size())
{
int tp = -pq.top();
printf("%d\n", tp);
pq.pop();
for (int there : vt[tp])
{
in[there]--;
if (in[there] == 0)
pq.push(-there);
}
n--; //cycle판단
}
if (n > 0)
printf("cycle");
return 0;
}
cycle 확인방법
정점의 횟수 만큼 반복문을 돌리다가 큐의 크기가 먼저 0이 된다면 cycle이 존재한다는것을 알 수 있다.
(사이클에 속하는 정점들이 존재하면 그 정점들은 모두 indegree가 1이상이라 큐에 들어가지 않기 때문!)
참고 : https://jason9319.tistory.com/93
Subscribe via RSS