拓扑排序(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(".....\n");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wz-archer/p/10670788.html