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的排列。

样例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;
}
    原文作者:拓扑排序
    原文地址: https://blog.csdn.net/update7/article/details/68961178
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞