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:拓扑编号的主要内容,如果未能解决你的问题,请参考以下文章
NOIP 车站分级 (luogu 1983 & codevs 3294 & vijos 1851) - 拓扑排序 - bitset