拓扑排序-Kahn算法

拓扑排序-Kahn算法

该算法的关键在于需要维护一个入度为0的顶点的集合:

每次从该集合中取出(如果要求输出时编号小的在前,可以用优先队列保存集合)一个顶点,将该顶点放入保存结果的List中。

紧接着循环遍历由该顶点引出的所有边,从图中移除这条边,同时获取该边的另外一个顶点,如果该顶点的入度在减去本条边之后为0,那么也将这个顶点放到入度为0的集合中。然后继续从集合中取出一个顶点…………

 

当集合为空之后,检查图中是否还存在任何边,如果存在的话,说明图中至少存在一条环路。不存在的话则返回结果List,此List中的顺序就是对图进行拓扑排序的结果。

 

题目链接:确定比赛名次(HDU – 1285 

 

代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#define INF 1<<29
using namespace std;
int in[510],n,m;
bool vis[510];
vector<int> vec[510];
void bfs()
{
    //优先队列存储,保证输出时编号小的靠前
    priority_queue<int,vector<int>,greater<int> > q;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++)
    {
        if(!in[i])//首先将入度为0的点入队(即没有前驱的顶点)
        {
            q.push(i);
            vis[i]=1;
        }
    }
    int flag=0;
    while(!q.empty())
    {
        int top=q.top(); q.pop();//取出top
        
        if(flag)
            printf(" ");//输出
        printf("%d",top);
        flag=1;
        
        for(int i=0;i<vec[top].size();i++)
        {
            int now=vec[top][i];
            in[now]--;//将top的所有直接后继顶点入度-1
            if(!vis[now] && !in[now])//如果这个顶点的入度为0,将它入队
            {
                vis[now]=1;
                q.push(now);
            }
        }
    }
    printf("\n");
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        int u,v;
        memset(in,0,sizeof(in));
        for(int i=1;i<=n;i++)
            vec[i].clear();
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&u,&v);
            vec[u].push_back(v);
            in[v]++;//v的入度加一
        }
        bfs();
    }
    return 0;
}

 

    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/u013852115/article/details/75947590
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞