POJ 1182 食物链(带权并查集)

题目链接:食物链

这题是带权并查集的经典题,用rank[i]表示i与i父亲的关系,0为同类,1为吃,2为被吃。

rank在压缩路径和合并过程的转化在纸上把所有情况归纳出来,就可以变成一个公式。

代码:

#include <stdio.h>
#include <string.h>

const int N = 50005;
int n, k, parent[N], rank[N], ans = 0;

int find(int x) {
	if (parent[x] == x) return x;
	else {
		int p = find(parent[x]);
		rank[x] = (rank[x] + rank[parent[x]]) % 3;
		parent[x] = p;
	}
	return parent[x];
}

int main() {
	scanf("%d%d", &n, &k);
	for (int i = 1; i <= n; i++) {
		parent[i] = i; rank[i] = 0;
	}
	while (k--) {
		int q, a, b;
		scanf("%d%d%d", &q, &a, &b);
		if (a > n || b > n || (q == 2 && a == b)) ans++;
		else {
			int pa = find(a), pb = find(b);
			if (pa == pb) {
				if ((rank[b] - rank[a] + 3) % 3 != q - 1) ans++;
			}
			else {
				parent[pb] = pa;
				rank[pb] = (rank[a] - rank[b] + q + 2) % 3;
			}
		}	
	}
	printf("%d\n", ans);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值