• HDU1285 裸的拓扑排序


    拓扑排序:

    拓扑排序是应用于有向无回路图(DAG)上的一种排序方式,对一个有向无回路进行拓扑排序后,所有的顶点形成一个序列,对所有边(u,v),满足u在v的前面。该序列说明了顶点表示的事件或 状态发生的整体顺序。

    比较经典的是在工程活动上,某些工程完成后,另一些工程才能继续,此时可以以工程为顶点,工程间的依赖关系为边建立图,用拓扑排序来求得所有工程的合理执行顺序。

    对一个DAG进行拓扑排序有两种方法,广度优先搜索和深度优先搜索

    这里介绍广度优先搜索,进行拓扑排序时,每次可以拿出的顶点一定是入度为0的点,即没有被指向的点,因为这样的点表示的事件没有依赖,在一个入度为0的点表示的事件执行完之后,它所指向的顶点所依赖的点就少了一个,所以我们可以先将所有入度为0的点加入一个队列中,然后依次将它们所指向的点的入度减1,再将入度变为0的点也依次加入队列中,这样最后就可以得到一个拓扑有序的序列。

    本题中说符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前,需要用到优先队列,每次从队列中取的是最小的那个元素

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <queue>
    using namespace std;
    const int maxn=510;
    int graph[maxn][maxn];//保存图
    int degree[maxn];//保存入度
    
    int main()
    {
        int n,m;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            memset(graph,0,sizeof(graph));
            memset(degree,0,sizeof(degree));
            for(int i=0;i<m;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                if(!graph[u][v])
                {
                    graph[u][v]=1;
                    degree[v]++;//v的入度++
                }
            }
            priority_queue<int,vector<int>,greater<int> >q;
            for(int i=1;i<=n;i++)
                if(degree[i]==0)
                q.push(i);
            bool first=1;
            while(!q.empty())
            {
                int cur=q.top();
                q.pop();
                if(first)
                {
                    cout<<cur;
                    first=0;
                }
                else
                    cout<<" "<<cur;
                for(int i=1;i<=n;i++)
                {
                    if(graph[cur][i])
                    {
                        degree[i]--;//相连的点的入度减1
                        if(degree[i]==0)//如果入度为0,加入队列
                            q.push(i);
                    }
                }
            }
            printf("
    ");
        }
        return 0;
    }
    /**
     * The Kahn's Topological Sort Algorithm in C++
     * Using the Adjecency List
     * Time Cost : O(|V|+|E|)
     * Author: Zheng Chen / Arclabs001
     * Copyright 2015 Xi'an University of Posts & Telecommunications
     */
    #include <iostream>
    #include <queue>
    #include <vector>
    using namespace std;
    
    const int N = 5; // The number of Vertex
    
    enum status {UNDISCOVERED,VISITED};
    
    struct Vertex
    {
        int inDegree, outDegree;
        int data;
        status _stat;
    }V[N];
    
    vector<int> AdjList[N];   //Using vector to simulate the adjlist
    queue<int> vertexQueue;   //The call queue
    /**
     * Initialize the graph as below:
    The Graph:
    
    0->1->3
    |  |  |
    / / /
    2->4<--
    
     * @return The pointer to the start vertex
     */
    Vertex* init_graph()
    {
        while(!vertexQueue.empty())
            vertexQueue.pop();
    
        for(int i=0; i<N; i++)
        {
            AdjList[i].clear();
            V[i]._stat = UNDISCOVERED;
            V[i].data = i;
        }
    
        V[0].inDegree = 0; V[0].outDegree = 2;
        V[1].inDegree = 1; V[1].outDegree = 3;
        V[2].inDegree = 1; V[2].outDegree = 1;
        V[3].inDegree = 1; V[3].outDegree = 1;
        V[4].inDegree = 3; V[4].outDegree = 0;
    
        AdjList[0].push_back(1); AdjList[0].push_back(2);
        AdjList[1].push_back(3); AdjList[1].push_back(4);
        AdjList[2].push_back(4);
        AdjList[3].push_back(4);
    
        return & V[0];
    }
    
    bool Topological_Sort()
    {
        for(int i=0; i<N; i++)
        {
            if(V[i].inDegree == 0)
                vertexQueue.push(i);
        }
    
        while(!vertexQueue.empty())
        {
            int top = vertexQueue.front();
            V[top].outDegree = 0;
            V[top]._stat = VISITED;
            int i=0;
    
            for(int v : AdjList[top])
            {
                --V[v].inDegree;
    
                AdjList[top][i++] = -1;
                if(V[v].inDegree == 0)
                    vertexQueue.push(v);
            }
            cout<<top<<" ";
    
            vertexQueue.pop();
        }
    
        for(int i=0; i<N; i++)
        {
            for(int v : AdjList[i])
                if(v != -1)
                {
                    return false;
                }
        }
    
        return true;
    }
    
    int main()
    {
        init_graph();
    
        bool status = Topological_Sort();
        if(status == false)
        {
            cout<<"Error! The graph has at least one cycle!"<<endl;
        }
        return 0;
    }
  • 相关阅读:
    KindEditor-编辑器配置参数属性
    泛型作为返回类型的写法
    ObservableCollection<T> 类
    常遇到的问题
    实现跨浏览器html5表单验证
    mysql 密码重置
    Web用户的身份验证及WebApi权限验证流程的设计和实现
    Discuz3.2 新用户插入数据库SQL
    3. 深入研究 UCenter API 之 加密与解密(转载)
    window.open实现模式窗口
  • 原文地址:https://www.cnblogs.com/kimsimple/p/6875660.html
Copyright © 2020-2023  润新知