POJ1182食物链 (并查集)

第一反应就是和那个搞基的虫子的题很像(poj2492 http://www.cnblogs.com/wenruo/p/4658874.html),不过是把种类从2变成了3。

错在很白痴的地方,卡了好久……

代码:

/*********************************************
Problem: 1182		User: G_lory
Memory: 972K		Time: 266MS
Language: G++		Result: Accepted
*********************************************/
#include <cstdio>
#include <cstring>

using namespace std;

const int N = 50005;

int par[N];
int rank[N];
int rel[N];	// 0: same, 1: father eat son, 2: son eat father

void init(int n)
{
	for (int i = 0; i <= n; ++i) {
		par[i] = i;
		rank[i] = 0;
		rel[i] = 0;
	}
}

int find(int x)
{
	if (par[x] == x) return x;
	return find(par[x]);
}

// return 1 means root eat x, return 2 mean x eat root, return 0 mean same
int rel_root(int x)
{
	int p, ans = 0;
	for (p = x; p != par[p]; p = par[p]) {
		ans = (ans + rel[p]) % 3;
	}
	return ans;
}

void unite(int x, int y, int c)
{
	int rootx = find(x);
	int rooty = find(y);
	if (rootx == rooty) return ;
	int relx = rel_root(x);
	int rely = rel_root(y);
	if (rank[rootx] < rank[rooty]) {
		par[rootx] = rooty;
		rel[rootx] = ((rely - relx - c) % 3 + 3) % 3;
	} else {
		par[rooty] = rootx;
		rel[rooty] = ((relx - rely + c) % 3 + 3) % 3;
	}
	if (rank[rootx] == rank[rooty]) ++rank[rootx];
}

bool same(int x, int y)
{
	return find(x) == find(y);
}

int main()
{
    int n, k;
    int ch, x, y;
    scanf("%d%d", &n, &k);
		int ans = 0;
		init(n);
		for (int i = 0; i < k; ++i) {
			scanf("%d%d%d", &ch, &x, &y);
			if (x > n || x <= 0 || y > n || y <= 0) {
				++ans;
				continue;
			}
			if (ch == 1) {
				if (same(x, y)) {
					if (rel_root(x) != rel_root(y)) ++ans;
				} else unite(x, y, 0);
			} else {
				if (same(x, y)) { // x eat y
					if ( !((rel_root(x) == 0 && rel_root(y) == 1) ||
						   (rel_root(x) == 1 && rel_root(y) == 2) ||
						   (rel_root(x) == 2 && rel_root(y) == 0)) )
							++ans;
				} else unite(x, y, 1);
			}
		}
		printf("%d
", ans);
    return 0;
}

  

并查集模板:

const int N = 300005;

int par[N];		// father
int rank[N];	// height

void init(int n)
{
	for (int i = 0; i < n; ++i) {
		par[i] = i;
		rank[i] = 0;
	}
}

int find(int x)
{
	if (par[x] == x) return x;
	return par[x] = find(par[x]); // 压缩路径
}

void unite(int x, int y)
{
	x = find(x); y = find(y);
	if (x == y) return ;
	if (rank[x] < rank[y]) par[x] = y;
	else par[y] = x;
	if (rank[x] == rank[y]) ++rank[x];
}

bool same(int x, int y)
{
	return find(x) == find(y);
}

  

原文地址:https://www.cnblogs.com/wenruo/p/4720888.html