我们将限制条件看成一些边,那么如果出现了环则无解,有解的图一定是一个 DAG。
很容易想到直接弄一个堆拓扑排序,但很容易发现这样是错的。
不难想到建立反图,拿一个大根堆跑拓扑排序,此时跑出的答案是要求答案的逆序。
代码很好写。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair <int, int> PII;
template <typename T>
inline T gi()
{
T x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return f * x;
}
const int N = 100003, M = N << 1;
int n, m, in[N];
int tot, head[N], ver[M], nxt[M];
map <PII, bool> p;
int ans[N];
inline void add(int u, int v) {ver[++tot] = v, nxt[tot] = head[u], head[u] = tot;}
int main()
{
//File("");
int T = gi <int> ();
while (T--)
{
n = gi <int> (), m = gi <int> ();
p.clear();
for (int i = 1; i <= m; i+=1)
{
int u = gi <int> (), v = gi <int> ();
p[make_pair(u, v)] = true;
}
memset(head, 0, sizeof head); tot = 0;
memset(in, 0, sizeof in);
for (auto it : p)
add(it.first.second, it.first.first), ++in[it.first.first];
priority_queue <int> q;
for (int i = 1; i <= n; i+=1) if (!in[i]) q.push(i);
int cnt = 0;
while (!q.empty())
{
int u = q.top(); q.pop();
ans[++cnt] = u;
for (int i = head[u]; i; i = nxt[i])
{
int v = ver[i];
if (!(--in[v])) q.push(v);
}
}
if (cnt != n) puts("Impossible!");
else
{
for (int i = cnt; i >= 1; i-=1) printf("%d ", ans[i]); puts("");
}
}
return 0;
}