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

题面

我们将限制条件看成一些边,那么如果出现了环则无解,有解的图一定是一个 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;
}
原文地址:https://www.cnblogs.com/xsl19/p/14084421.html