拓扑排序(dfs)
Posted wz-archer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拓扑排序(dfs)相关的知识,希望对你有一定的参考价值。
问题:
对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。(如下图)
思想:
1.找到一个没有子节点的节点,他就是最后一个要做的事情。
2.删除这个子节点。
3.在当前图里再次寻找没有子节点的节点。
4.删除到没有节点时,将删除顺序倒过来就是拓扑排序的顺序。
补:如果已经找不到没有子节点的节点,说明这张图有环,不存在拓扑排序。
代码:
#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> using namespace std; const int maxn=1e3+10; int G[maxn][maxn]; int n; int c[maxn]; int topo[maxn],t; bool dfs(int u){ c[u]=-1; //c[u]==-1表示正在查找这个点的子节点 for(int v=0;v<n;v++)if(G[u][v]){ if(c[v]<0)return false; //因为G[u][v]!=0才会进入这里,代表v时u的子节点。 //c[v]==-1,代表正在查找v的子节点,说明u时v的子节点 //说明u和v之间是一个环 else if(!c[v]&&!dfs(v))return false; /*这句话理解为 if(!c[v]){ //如果点v没有查找过,那么查找点v的子节点 if(!dfs(v)){ //如果v的子节点内存在环,返回false return false; } } */ } c[u]=1;topo[--t]=u;//没有子节点的节点会最先到达这里 return true; } bool toposort(){ t=n; memset(c,0,sizeof(c)); for(int u=0;u<n;u++) if(!c[u]) if(!dfs(u)) return false; return true; } int main() { int m; memset(G,0,sizeof(G)); scanf("%d%d",&n,&m); for(int i=0;i<m;i++){ int a,b; scanf("%d%d",&a,&b); G[a][b]=1; } if(toposort()) for(int i=0;i<n;i++){ printf("%d ",topo[i]); } else printf("..... "); return 0; }
以上是关于拓扑排序(dfs)的主要内容,如果未能解决你的问题,请参考以下文章
逆拓扑排序实现思想以及通过DFS算法实现逆拓扑排序(C语言)