拓扑排序

拓扑排序

  看了一下拓扑排序,来和大家分享一下,什么是拓扑排序。

  定义:将有向图中的顶点以线性方式进行排序。即对于任何连接自顶点u到顶点v的有向边uv,在最后的排序结果中,顶点u总是在顶点v的前面。

  是不是有点抽象,来举个例子,比如在我玩部落冲突这款游戏时,在打哥布林的时候我们想要打第4关,是不是一定要打过第3关,不能跳。

  

  看我们要是想打丹妮男孩是不是必须打掉哥布林营地,那么是不是确定了哥布林营地一定在丹妮男孩前面,那么我们将这个图转换成一个序列后,在这个拓扑序列中,那么哥布林营地的位置一定是处于丹妮男孩前面的。每一个关卡相当于我们的节点,而关卡之间的关系相当于我们的有向边。他们之间存在前后关系。

  还有我们不是所有有向图都能进行拓扑排序,还是上面那个例子铜墙铁壁的前提是将“丹妮男孩”,“奥马哈海滩”都闯过了才能闯铜墙铁壁,而不能直接闯铜墙铁壁,负责就越闯越回去了,难度越闯越弱。所以在拓扑排序中不能存在环,他们之间存在依赖关系,所以拿来图谱排序的图一定只能是有向无环图。

bfs拓扑排序:

在用bfs求有向无环图的拓扑序,我们需要下记录每个点的入度,然后不断将入度为0 的点输出删掉,每删掉一个点都要将他所能到达的点的入度减一,直到点被删完。

 

代码如下:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <queue>
 5 using namespace std;
 6 
 7 const int maxn = 1000 + 5;
 8 
 9 int n,m;
10 
11 vector<int >G[maxn];
12 int indeg[maxn];
13 bool vis[maxn];
14 
15 void bfs(int u){
16   queue<int >Q;
17   Q.push(u);
18   while(!Q.empty()){
19     int s = Q.front();Q.pop();
20     printf("%d\n",s);//打印
21     vis[s] = true;
22     for(int i = 0;i < G[s].size(); i++){
23       int v = G[s][i];
24       indeg[v]--;//更新入度,也相当于删边
25       // printf("s=%d v=%d 的入度 = %d\n",s,v,indeg[v]);
26       if(indeg[v] == 0 && !vis[v]){
27         vis[v] = true;
28         Q.push(v);
29       }
30     }
31   }
32 }
33 
34 int main(){
35   scanf("%d%d",&n,&m);
36   for(int i = 1;i <= m; i++){
37     int u,v;
38     scanf("%d%d",&u,&v);
39     indeg[v]++;//记录每个点的入度
40     G[u].push_back(v);
41   }
42   for(int i = 0;i < n; i++){
43     if(indeg[i] == 0 && !vis[i]){//只从入度为0的进入
44       bfs(i);
45     }
46   }
47 }

 

posted @ 2016-12-22 20:26  fengsz  阅读(187)  评论(0编辑  收藏  举报