【拓扑排序】Topological Sort Aizu - GRL_4_B

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;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值