拓扑排序
作者:互联网
基于BFS的拓扑排序
先将所有入度为0的点放入队列中(顺序无关紧要),每次将队首弹出的点加入拓扑序列中,然后将该点所有的相邻点入度减1,将入度减为0的点入队。
当队列为空时,若所有点都以加入拓扑序列,则完成退出,反之该图不存在拓扑序列。
参考代码
void topo(){
for(int i=1;i<=n;++i){
if(ind[i]==0){q.push(i);
ts[++tot]=i;}
}
int now,next;
while(!q.empty()){
now=q.front();
q.pop();
for(int i=0;i<node[now].size();++i){
next=node[now][i];
if(--ind[next]==0){
q.push(next);
ts[++tot]=next;
}
}
}
基于DFS的拓扑排序
首先在一个图中使用dfs会产生一个深搜优先生成树。
黑色的边叫树边,这些边构成了深搜优先生成树。
红色的边叫返祖边,这些边指向祖先。
绿色的边叫前向边,这些边直线孙子,孙孙子。。。(注意不包括儿子)。
蓝色的边叫横插边,这些边上的两个节点没有子孙关系(相对于深搜优先生成树来讲)。
显然一个图中只有不产生返祖边才能有拓扑排序。
bool dfs(int s){
vis[s]=-1;
int next;
for(int i=0;i<node[s].size();++i){
next=node[s][i];
if(vis[next]<0)return false;//发现返祖边,-1是为了区分子孙与祖先
if(vis[next]==0&&!dfs(next))return false;
}
vis[s]=1;
ts[tot--]=s;//加入拓扑排序
return true;
}
bool topo(){
tot=n;
bool f=1;
for(int i=1;i<=n;++i){
if(ind[i]==0&&vis[i]==0){
f=dfs(i);
if(f==0)return false;
}
}
}
标签:int,拓扑,dfs,返祖,序列,排序 来源: https://www.cnblogs.com/hetailang/p/16219830.html