题目链接

拓扑排序(经典)

有两个地方是需要注意的: 1.在存在多解得情况下,并不是按字典序最小输出解;假设这里有两个约束条件 2 < 4, 3 < 1,这两个约束条件并没有相互影响,所以 2,4,3,1 和 3 1 2 4都是可行的,但是题目要求的是,如果有多解,优先考虑1最轻,所以,正解应该是3,1,2,4。有1的那部分优先放在前面。这里的做法是逆向考虑,如果正向的话,同样使用上面的列子,会最先判断2和3的大小,却忽略了后面的1,所以从尾部先考虑,谁大先填谁,这样填数是不会错的。

2.题目要求输出的不是编号的顺序而是重量的顺序,这里不要搞错了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>

using namespace std;

const int Maxn = 4e4+10;

int indeg[220], ans[Maxn], Hash[Maxn];
bool vis[220];
vector <int> G[220];

int main(void)
{
	int T;
	scanf("%d", &T);
	while(T--) {
		int n, m;
		scanf("%d%d", &n, &m);
		memset(indeg, 0, sizeof(indeg));
		for(int i = 1; i <= n; ++i) {
			vis[i] = true;
			G[i].clear();
		}
		int u, v;
		for(int i = 0; i < m; ++i) {
			scanf("%d%d", &u, &v);
			G[v].push_back(u);
			indeg[u]++;
		}
		int p = 0;
		queue<int> qu;
		while(1) {
			for(int i = n; i >= 1; --i) if(!indeg[i] && vis[i]) {
				qu.push(i); break;
			}
			if(qu.size() == 0) break;
			while(!qu.empty()) {
				int u = qu.front(); qu.pop();
				ans[p++] = u;
				vis[u] = false;
				for(int i = 0; i < G[u].size(); ++i) {
					int v = G[u][i];
					indeg[v]--;
				}
			} 
		}
		if(p != n) printf("-1");
		else {
			for(int i = p-1; i >= 0; --i) Hash[ans[i]] = n-i;
			for(int i = 1; i <= n; ++i) {
				if(i == 1) printf("%d", Hash[i]);
				else printf(" %d", Hash[i]);
			}
		}
		puts("");
	}
	return 0;
}