码迷,mamicode.com
首页 > 其他好文 > 详细

Vijos1790:拓扑编号

时间:2016-04-03 23:51:27      阅读:291      评论:0      收藏:0      [点我收藏+]

标签:

描述

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;
}    

 

Vijos1790:拓扑编号

标签:

原文地址:http://www.cnblogs.com/program-ccc/p/5350903.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!