【题目链接】
【思路要点】
- 反向建边拓补排序就行。
- 时间复杂度\(O(D*(N+M))\)。
【代码】
#include<bits/stdc++.h> using namespace std; #define MAXN 100005 int d[MAXN], n, m, now, tot, to; int home[MAXN], ans[MAXN], cnt[MAXN], colour[MAXN]; vector <int> a[MAXN]; bool func() { int l = 1, r = 0; static int q[MAXN]; for (int i = 1; i <= n; i++) if (d[i] == 0) q[++r] = i; while (l <= r) { int tmp = q[l]; for (unsigned i = 0; i < a[tmp].size(); i++) { d[a[tmp][i]]--; if (d[a[tmp][i]] == 0) q[++r] = a[tmp][i]; } l++; } return r < n; } void visit(int pos) { if (colour[pos] != now) return; colour[pos] = to; tot++; for (unsigned i = 0; i < a[pos].size(); i++) visit(a[pos][i]); } int main() { int T; scanf("%d", &T); while (T--) { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) a[i].clear(); memset(d, 0, sizeof(d)); for (int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); a[y].push_back(x); d[x]++; } if (func()) { printf("Impossible!\n"); continue; } memset(home, 0, sizeof(home)); memset(ans, 0, sizeof(ans)); memset(cnt, 0, sizeof(cnt)); memset(colour, 0, sizeof(colour)); home[0] = n + 1; cnt[0] = n + 1; for (int i = 1; i <= n; i++) { now = colour[i]; tot = 0; to = i; visit(i); home[i] = home[now] - cnt[now] + tot; cnt[i] = tot; cnt[now] -= tot; ans[home[i]] = i; } for (int i = 1; i < n; i++) printf("%d ", ans[i]); printf("%d \n", ans[n]); } return 0; }