拓扑排序(经典)
有两个地方是需要注意的: 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;
}
浙公网安备 33010602011771号