题解【LOJ2114】「HNOI2015」菜肴制作


题面

我们将限制条件看成一些边,那么如果出现了环则无解,有解的图一定是一个 DAG。

很容易想到直接弄一个堆拓扑排序,但很容易发现这样是错的。

不难想到建立反图,拿一个大根堆跑拓扑排序,此时跑出的答案是要求答案的逆序。

代码很好写。

#include 

using namespace std;

typedef long long LL;
typedef pair  PII;

template 
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  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  ();
	while (T--)
	{
		n = gi  (), m = gi  ();
		p.clear();
		for (int i = 1; i <= m; i+=1)
		{
			int u = gi  (), v = gi  ();
			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  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;
}