Topological Sort Aizu - GRL_4_B
A directed acyclic graph (DAG) can be used to represent the ordering of tasks. Tasks are represented by vertices and constraints where one task can begin before another, are represented by edges. For example, in the above example, you can undertake task B after both task A and task B are finished. You can obtain the proper sequence of all the tasks by a topological sort.
Given a DAG GG, print the order of vertices after the topological sort.
Input
A directed graph GG is given in the following format:
|V||E||V||E|
s0t0s0t0
s1t1s1t1
:
s|E|−1t|E|−1s|E|−1t|E|−1
|V||V| is the number of vertices and |E||E| is the number of edges in the graph. The graph vertices are named with the numbers 0,1,...,|V|−10,1,...,|V|−1 respectively.
sisi and titi represent source and target nodes of ii-th edge (directed).
Output
Print the vertices numbers in order. Print a number in a line.
If there are multiple possible solutions, print any one of them (the solution is judged by a special validator).
Constraints
- 1≤|V|≤10,0001≤|V|≤10,000
- 0≤|E|≤100,0000≤|E|≤100,000
- There are no parallel edges in GG
- There are no self loops in GG
Sample Input
6 6
0 1
1 2
3 1
3 4
4 5
5 2
Sample Output
0
3
1
4
5
2
//拓扑排序
//挑战程序设计竞赛2算法和数据结构P284
/*所谓图的拓扑排序,就是让图中全部有向边都由左指向右,同时将所有顶点排在一条水平线上。*/
/*
广度优先搜索实现的拓扑排序
topologicalSort()
将所有结点的color[u]设置为WHITE
设置所有结点的u的入度indeg[u]
for u 从 0 至 |V|-1
if indeg[u]==0 && color[u]==WHITE
bfs(u)
bfs(int s)
Q.push(s)//队列
color[s]=GRAY
while Q不为空
u=Q.dequeue()
out.push_back(u) //将度为0的顶点加入链表
for 与u相邻的结点v
indeg[v]--
if indeg[v]==0 && color[v]==WHITE
color[v]=GRAY
Q.enqueue(v)
上述算法根据广度优先搜索的顺序依次访问入度为0的顶点,并将访问过的顶点添加至链表末尾。
该算法将访问过的顶点u视为“已结束”,同时将下一顶点v(从u出发的边指向的顶点)的入度减1。
这一操作相当于删除边。不断地删除边可以使v的入度逐渐降为0,为此我们便可以访问顶点v,然后将v加入链表。
*/
/*
用递归思想和深度优先搜索实现的拓扑排序
topologicalSort()
将所有结点的color[u]设置为WHITE
for s从0至|V|-1
if color[s]==WHITE
dfs(s)
dfs(u)
color[u]=GRAY
for 与u相邻的结点v
if color[v]==WHITE
dfs(v)
out.push_front(u) //将访问结束的顶点逆向添加至链表
上述算法通过深度优先搜索访问顶点,并把访问的顶点添加至链表开头。这里要注意,由于深度优先搜索是逆向确定各顶点的拓扑顺序,因此顶点式添加至链表“开头”的。
*/
/*用深度优先搜索和广度优先搜索实现的拓扑排序算法复杂度同为O(|V|+|E|)。考虑到大规模图容易引起栈溢出,因此不涉及递归的广度优先搜索更为合适。*/
//广度优先搜索实现的拓扑排序
#include <iostream>
#include <vector>
#include <queue>
#include <list>
#define MAX 1000002
using namespace std;
vector<int> G[MAX];
list<int> out;
bool vis[MAX];
int N;
int indeg[MAX];
void bfs(int s) {
queue<int> q;
q.push(s);
vis[s] = true;
while (!q.empty()) {
int u = q.front();
q.pop();
out.push_back(u);
for (int i = 0; i < G[u].size(); ++i) {
int v = G[u][i];
indeg[v]--;
if (indeg[v] == 0 && !vis[v]) {
vis[v] = true;
q.push(v);
}
}
}
}
void topologicalSort() {
for (int i = 0; i < N; ++i) {
indeg[i] = 0;
}
for (int u = 0; u < N; ++u) {
for (int i = 0; i < G[u].size(); ++i) {
indeg[G[u][i]]++;
}
}
for (int u = 0; u < N; ++u) {
if (indeg[u] == 0 && !vis[u]) {
bfs(u);
}
}
for (list<int>::iterator it = out.begin(); it != out.end(); it++) {
cout << *it << endl;
}
}
int main() {
int s, t, M;
cin >> N >> M;
for (int i = 0; i < N; ++i) vis[i] = false;
for (int i = 0; i < M; ++i) {
cin >> s >> t;
G[s].push_back(t);
}
topologicalSort();
return 0;
}
//深度优先搜索实现的拓扑排序
#include <iostream>
#include <vector>
#include <list>
using namespace std;
const int MAX = 100000;
vector<int> G[MAX];
list<int> out;
bool vis[MAX];
int N;
void dfs(int u) {
vis[u] = true;
for (int i = 0; i < G[u].size(); ++i) {
int v = G[u][i];
if (!vis[v]) dfs(v);
}
out.push_front(u);
}
int main() {
int s, t, M;
cin >> N >> M;
for (int i = 0; i < N; ++i) vis[i] = false;
for (int i = 0; i < M; ++i) {
cin >> s >> t;
G[s].push_back(t);
}
for (int i = 0; i < N; ++i) {
if (!vis[i]) dfs(i);
}
for (list<int>::iterator it = out.begin(); it != out.end(); it++) {
cout << *it << endl;
}
return 0;
}