【vijos】1790 拓扑编号(拓扑+贪心)

https://vijos.org/p/1790

好神的贪心题。。

一开始我也想到了贪心,但是是错的。。sad

就是因为每一个节点的编号与逆图的子树有关,且编号一定是>=子树的儿子+1的。但是想了想很快发现不可做。。因为这种dfs牵扯到的东西太多了。

然后我想到这些约束是不是和差分约束有关,然后就脑补,可是后边发现这也是不可做的,因为差分约束算出来的不是编号。sad。。

无奈看题解。

sad

这个和我第一个想法有关。。。

因为编号一定是>=逆图的子树儿子+1,显然如果每一次将编号从大向小的放是满足这一性质的。

建一个逆的图,那么就是每次取最大的标号度为0的点,那么这个点的编号就是当前剩余的编号。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define printarr2(a, b, c) for1(_, 1, b) { for1(__, 1, c) cout << a[_][__]; cout << endl; }
#define printarr1(a, b) for1(_, 1, b) cout << a[_] << '\t'; cout << endl
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
inline const int max(const int &a, const int &b) { return a>b?a:b; }
inline const int min(const int &a, const int &b) { return a<b?a:b; }

priority_queue<int> id;
const int N=100005, M=200005;
int ihead[N], cnt, n, m, tot, in[N], a[N];
struct ED { int to, next; }e[M];
void add(int u, int v) {
	e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v;
}

int main() {
	read(n); read(m); tot=n+1;
	rep(i, m) {
		int u=getint(), v=getint();
		add(v, u); ++in[u];
	}
	for1(i, 1, n) if(in[i]==0) id.push(i);
	while(!id.empty()) {
		int u=id.top(); id.pop();
		a[u]=--tot;
		for(int i=ihead[u]; i; i=e[i].next) {
			--in[e[i].to];
			if(in[e[i].to]==0) id.push(e[i].to);
		}
	}
	for1(i, 1, n) printf("%d ", a[i]);
	return 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的排列。

样例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

posted @ 2014-10-08 07:15  iwtwiioi  阅读(415)  评论(0编辑  收藏  举报