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("\n");
    }
    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;
}

 

posted @ 2017-05-31 10:03  kimsimple  阅读(332)  评论(0编辑  收藏  举报