Vijos1790:拓扑编号

Posted vCoders

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}    

 

以上是关于Vijos1790:拓扑编号的主要内容,如果未能解决你的问题,请参考以下文章

vijos 拓扑编号

NOIP 车站分级 (luogu 1983 & codevs 3294 & vijos 1851) - 拓扑排序 - bitset

vijos1736-铺地毯

Vijos p1123 均分纸牌

Vijos1459 车展 (数学)

如何创建片段以重复变量编号中的代码行