有向无环图中的拓扑排序

´有向无环图(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;
 } 

 

posted @ 2017-01-25 16:38  Mr.9Pounds15Pence  阅读(773)  评论(0编辑  收藏  举报