知识点:拓扑排序
难度:4
这个题属于那种你做出来了,但是还是觉得自己不是很掌握的题,首先题意讲的很详细,但是不是第3个样例的话,也不知道它真正的意思,它的意思就是原本的顺序是1到n,除非是有那种输入给定的顺序,那么要尽量按照从小到大的顺序输出,这个和字典序是不一样的,看第三个样例就知道,然后想了半天,突发奇想,要不建个反图,求字典序最大的拓扑序,然后输出的时候逆序输出,就这个样子写了,用的大根堆,最后竟然过了,但是怎么证明这个是对的,还是写不出来,这就跟做贪心题一样恶心,明明写出来了,但是觉得这道题还是自己不会做一样
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int n, m, tot, ver[N], nxt[N], head[N];
int in[N], a[N], cnt;
void add(int x, int y) {
ver[++tot] = y;
nxt[tot] = head[x]; head[x] = tot;
}
void solve() {
priority_queue<int> q;
for (int i = 1; i <= n; i++) {
if (!in[i]) q.push(i);
}
while (!q.empty()) {
int now = q.top(); q.pop();
a[++cnt] = now;
for (int i = head[now]; i; i = nxt[i]) {
int y = ver[i];
if (--in[y] == 0) q.push(y);
}
}
}
int main() {
int T;
cin >> T;
while (T--) {
tot = cnt = 0;
memset(head, 0, sizeof(head));
memset(in, 0, sizeof(in));
cin >> n >> m;
map<pair<int, int>, int> mp;
while (m--) {
int x, y;
cin >> x >> y;
if (mp[make_pair(x, y)]) continue;
mp[make_pair(x, y)] = 1;
add(y, x);
in[x]++;
}
solve();
if (cnt != n) cout << "Impossible!\n";
else {
reverse(a + 1, a + n + 1);
for (int i = 1; i <= n; i++) {
cout << a[i] << (i < n ? " " : "\n");
}
}
}
return 0;
}