Vijos1790:拓扑编号

描述

H国有n个城市,城市与城市之间有m条单向道路,满足任何城市不能通过某条路径回到自己。

现在国王想给城市重新编号,令第i个城市的新的编号为a[i],满足所有城市的新的编号都互不相同,并且编号为[1,n]之间的整数。国王认为一个编号方案是优美的当且仅当对于任意的两个城市i,j,如果i能够到达j,那么a[i]应当<a[j]。

优美的编号方案有很多种,国王希望使1号城市的编号尽可能小,在此前提下,使得2号城市的编号尽可能小...依此类推。

格式

输入格式

第一行读入n,m,表示n个城市,m条有向路径。

接下来读入m行,每行两个整数:x,y
表示第x个城市到第y个城市有一条有向路径。

输出格式

输出一行:n个整数
第i个整数表示第i个城市的新编号a[i],输出应保证是一个关于1到n的排列。

输入:

5 4
4 1
1 3
5 3
2 5

输出:

2 3 5 1 4

思路:按反向边构图,拓扑排序时取出序号最大的结点,赋予当前最大编号。

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=100005;
struct Edge{
    int to,next;
};
Edge es[200005];
int head[MAXN],tot;
int n,m;
int id[MAXN],deg[MAXN];
void addedge(int u,int v)
{
    es[tot].to=v;
    es[tot].next=head[u];
    head[u]=tot++;
}
void topsort()
{
    int cnt=n;
    priority_queue<int> que;
    for(int i=1;i<=n;i++)
        if(deg[i]==0)
        {    
            que.push(i);
        }
    while(!que.empty())
    {
        int now=que.top();que.pop();
        id[now]=cnt--;
        for(int i=head[now];i!=-1;i=es[i].next)
        {
            int u=es[i].to;
            deg[u]--;
            if(deg[u]==0)
            {    
                que.push(u);
            }
        }
    }
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for(int i=0;i<m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        addedge(v,u);
        deg[u]++;
    }
    topsort();
    for(int i=1;i<=n;i++)
    {
        printf("%d%c",id[i],i==n?'\n':' ');
    }
    return 0;
}    

 

posted on 2016-04-03 21:54  vCoders  阅读(197)  评论(0编辑  收藏  举报

导航