首页 > 编程语言 > 详细

有向无环图中的拓扑排序

时间:2017-01-25 17:33:38      阅读:303      评论:0      收藏:0      [点我收藏+]
′有向无环图(DAG),指不存在环的有向图
′点的入度,指以这个点为结束点的边数
′点的出度,指以这个点为出发点的边数
′拓扑序就是对于节点的一个排列使得若(u,v)∈E,那么u在排列中出现的位置一定在v前面
′而拓扑排序,则是一个用于求解拓扑序的方法(只需要求出一组解)
 

一个合法的拓扑序(1 2 4 3 5)

技术分享

 

′我们要如何求出其中一个拓扑序?
′我们观察到拓扑序的定义是若(u,v)∈E,那么u在排列中出现的位置一定在v前面
′也就是说,考虑一个节点u,当我们删除u在排列中的前面所有节点之后,u的入度应该为0
′因此,我们就得到了一个大致的算法思路。
 
′拓扑排序:
′循环n次:
′选取一个入度为0且仍存在(未出现在排列当中)的点v
′删除点v以及从点v出发的所有边,更新剩余点的入度
′选取的v的序列则是一个合法的拓扑序
 
#include <bits/stdc++.h>
using namespace std;

const int maxn=100000+15;
const int maxm=100000+15;
struct Edge
{
    int x,y,next;
    Edge(int x=0,int y=0,int next=0):x(x),y(y),next(next){}
}edge[maxm];
int sumedge,head[maxn];
int n,m;
int ins(int x,int y)
{
    edge[++sumedge]=Edge(x,y,head[x]);
    return head[x]=sumedge;
}
int h,t,line[maxn],ind[maxn];
int money[maxn];
bool boo[maxn];
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        ins(u,v);
        ind[v]++;
    }
    h=1;t=0;
    int ss=888;
    for (int i=1;i<=n;i++)
     if (ind[i]==0)
         line[++t]=i,money[i]=ss;
//    dp[i]=max(dp[j])+1 ((j,i))
    for (;h<=t;) 
    {
        ss++;
        int now=t;
        for (;h<=now;h++)
         for (int u=head[line[h]];u;u=edge[u].next)
         {
            ind[edge[u].y]--;
            if (ind[edge[u].y]==0) 
             line[++t]=edge[u].y,money[i]=ss;
         }
    }
    for (int i=1;i<=n;i++) printf("%d ",line[i]);
    printf("\n");
    return 0;
 } 

 

有向无环图中的拓扑排序

原文:http://www.cnblogs.com/9pounds15pence/p/6349706.html

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