首页 > 编程语言 > 详细

拓扑排序

时间:2019-10-26 20:05:03      阅读:87      评论:0      收藏:0      [点我收藏+]

拓扑排序

  • 对于DAG内所有节点,生成的序列
  • DAG内所有节点出现且仅出现一次
  • 若u->v,则排序时u的位置在v前面
  • 可用于判环

 

#include <iostream>
#include <queue>
using namespace std;
const int maxn=1000;

int head[maxn],cnt;
struct edge{
    int to,next,w;
}e[maxn*2];

void add_edge(int u,int v,int w){
    cnt++;
    e[cnt].next=head[u];
    e[cnt].to=v;
    e[cnt].w=w;
    head[u]=cnt;
}

queue<int> q;
int in[maxn],p;        //in[]:入度  p:计数器/指针 
int topo[maxn];        //topo[]:拓扑序 
bool toposort(int n) {        //n为图中的节点数 
    for(int u=1;u<=n;u++)    //遍历所有节点出度 
    {
        if(!in[u])    //若入度==0,则放入队列 
        {
            q.push(u);    
        }
    }
    while(!q.empty())
    {
        int u=q.front();    //取出的节点顺序为topo序 
        q.pop();
        topo[++p]=u;
        if(p>n)    return false;    //若p>n,说明一定有环(拓扑序内的节点数一定与DAG中节点数相同) 
        for(int i=head[u];i;i=e[i].next) {    //链遍历 
            int v=e[i].to;    
            in[v]--;        //每一个与u相连的点入度-1 
            //work()    拓扑排序往往不只是单纯排序,可根据情况在此执行work[eg.拓扑上的DP] 
            if (!in[v])    //若v入度为0,则v入队 
            {
                q.push(v);
            } 
        }
    }
    if(p!=n)    return false;    //因为有可能一开始队列就是空的,所以再次特判 
    return true;
}

void output(int n){
    for(int i=1;i<=n;i++)
        cout<<topo[i]<<" ";
}

int main(){
    int n,m;
    int u,v,w;
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        cin>>u>>v;
        add_edge(u,v,1);
        in[v]++;        //加边的时候顺便初始化入度 
    }
    if(toposort(n))
        output(n);
    else cout<<"NO";
    return 0;
}

 

拓扑排序

原文:https://www.cnblogs.com/kohano/p/11744451.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!