[CQOI2013]图的逆变换

题解懒得写 转自 http://tisu.is-programmer.com/posts/38862.html

如果在新图中存在 i->k 和 j->k

那么在原图里一定是这样的

所以我们可以发现,如果存在i->k和j->k

但只存在i->t或j->t其中之一,则新图不合法。

mycode:

/**
 * Problem:Inverse
 * Author:Shun Yao
 * Time:2013.5.27
 * Result:Accepted
 */

#include <cstring>
#include <cstdlib>
#include <cstdio>

using namespace std;

long tot;
class gnode {
public:
	long v;
	gnode *next;
	gnode() {}
	~gnode() {}
	gnode(long V, gnode *ne):v(V), next(ne) {}
} *g[305], G[90005];
void add(long x, long y) {
	g[x] = &(G[tot++] = gnode(y, g[x]));
}

long f[305], s[305];

int main() {
	long T, n, m, i, j, k, x, y;
	char ff;
	gnode *e;
	freopen("inverse.in", "r", stdin);
	freopen("inverse.out", "w", stdout);
	scanf("%ld", &T);
	while (T--) {
		scanf("%ld%ld", &n, &m);
		for (i = 0; i < n; ++i)
			g[i] = 0;
		tot = 0;
		for (i = 1; i <= m; ++i) {
			scanf("%ld%ld", &x, &y);
			add(x, y);
		}
		memset(f, -1, sizeof f);
		memset(s, 0, sizeof s);
		ff = 1;
		for (i = 0; i < n; ++i)
			if (g[i]) {
				j = f[g[i]->v];
				k = 0;
				for (e = g[i]; e; e = e->next)
					if (f[e->v] == j)
						++k;
					else {
						ff = 0;
						break;
					}
				if (j == -1) {
					for (e = g[i]; e; e = e->next) {
						f[e->v] = i;
						s[e->v] = k;
					}
				}
				ff = ff && s[g[i]->v] == k;
				if (!ff)
					break;
			}
		if (!ff)
			puts("No");
		else
			puts("Yes");
	}
	fclose(stdin);
	fclose(stdout);
	return 0;
}
原文地址:https://www.cnblogs.com/hsuppr/p/3103971.html