题目链接
描述
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的排列。
样例1
样例输入1
5 4
4 1
1 3
5 3
2 5
样例输出1
2 3 5 1 4
限制
每个测试点1s
提示
30%的测试点满足:n <= 10, m <= 10
70%的测试点满足:n <= 1000, m <= 10000
100%的测试点满足:n <= 100000, m <= 200000
输入数据可能有重边,可能不连通,但保证是有向无环图。
来源
Topcoder
//逆拓扑排序
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
const int mn=100000+10,mm=200000+10;
using namespace std;
int n,m,cnt[mn],a[mn],kk=1;
vector<int> g[mn];
priority_queue<int> q;
int main(){
int u,v;
scanf("%d%d",&n,&m);
while(m--){
scanf("%d%d",&u,&v);
g[v].push_back(u);
cnt[u]++;//v的入度
}
for(int i=1;i<=n;i++)
if(!cnt[i])
q.push(i);
int nt=n;
while(!q.empty()){
int k=q.top();
q.pop();
a[k]=(nt--);
for(int i=0;i<g[k].size();i++){
if(!(--cnt[g[k][i]])) q.push(g[k][i]);
}
}
for(int i=1;i<=n;i++)
printf("%d ",a[i]);
return 0;
}