美文网首页
拓扑排序(Topological Sorting)

拓扑排序(Topological Sorting)

作者: Gitfan | 来源:发表于2017-08-04 22:28 被阅读0次

    拓扑排序(Topological Sorting)
    拓扑排序(Topological Sorting)是一个有向无环图(DAG, Directed Acyclic Graph)的所有顶点的线性序列。DAG的判定
    拓扑排序的时间复杂度为O ( V + E ),因为DFS的时间复杂度度为O ( V + E )
    该序列必须满足下面两个条件:

    • 每个顶点出现且只出现一次。
    • 若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面。
      有向无环图(DAG)才有拓扑排序,非DAG图没有拓扑排序一说。
      例如,下面这个图:


    它是一个 DAG 图,那么如何写出它的拓扑排序呢?这里说一种比较常用的方法:

    • 1.从 DAG 图中选择一个 没有前驱(即入度为0)的顶点并输出。
    • 2.从图中删除该顶点和所有以它为起点的有向边。

    重复 1 和 2 直到当前的 DAG 图为空或当前图中不存在无前驱的顶点为止。后一种情况说明有向图中必然存在环。



    于是,得到拓扑排序后的结果是 { 1, 2, 4, 3, 5 }。

    通常,一个有向无环图可以有一个或多个拓扑排序序列。

    #include <cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int MAXN=100010;
    vector<int> graph[MAXN];
    int in[MAXN];
    void topoSort(int n)
    {
        vector<int> zero;//0入度点
        vector<int> result;//排序结果
        for(int i=1;i<=n;i++)
        {
            if(in[i]==0) zero.push_back(i);
        }
        while(!zero.empty())
        {
            int curr=zero.back();
            zero.pop_back();
            result.push_back(curr);
            int len=graph[curr].size();
            for(int i=0;i<len;i++)
            {
                int v=graph[curr][i];
                in[v]--;
                if(in[v]==0) zero.push_back(v);
            }
        }
        if(result.size()!=n)
        {
            printf("Not DAG, fail\n");
            return;
        }
        for(int i=0;i<result.size();i++)
        {
            printf("%d\n",result[i]);
        }
    }
    int main()
    {
        int n,m,a,b;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            memset(graph,0,sizeof(graph));
            memset(in,0,sizeof(in));
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&a,&b);
                graph[a].push_back(b);
                in[b]++;
            }
            topoSort(n);
        }
    }
    

    还有一种直观的方法是利用DFS,容易知道拓扑排序的序列为所有顶点的逆后续排列(ReversePostOrder)

    #include <cstdio>
    #include<cstring>
    #include<vector>
    #include<stack>
    using namespace std;
    const int MAXN=100010;
    vector<int> graph[MAXN];
    stack<int> result;//排序结果
    int vis[MAXN];
    bool DFS(int u)
    {
        if(vis[u]==2) return true;
        vis[u]=2;
        int len=graph[u].size();
        for(int i=0;i<len;i++)
        {
            int v=graph[u][i];
            if(vis[v]==0)
            {
                if(DFS(u)) return true;
            }
            else if(vis[v]==2) return true;
        }
        vis[u]=1;
        result.push(u);
        return false;
    }
    void topoSort(int n)
    {
        memset(vis,0,sizeof(vis));
        bool flag=false;
        for(int i=1;i<=n;i++)
        {
            if(vis[i]==0)
            {
                if(DFS(i))
                {
                    flag=true;
                    break;
                }
            }
        }
        if(flag)
        {
            printf("Not DAG, fail\n");
            return;
        }
        while(!result.empty())
        {
            printf("%d\n",result.top());
            result.pop();
        }
    }
    int main()
    {
        int n,m,a,b;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            memset(graph,0,sizeof(graph));
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d",&a,&b);
                graph[a].push_back(b);
            }
            topoSort(n);
        }
    }
    

    相关文章

      网友评论

          本文标题:拓扑排序(Topological Sorting)

          本文链接:https://www.haomeiwen.com/subject/ebnmlxtx.html