POJ_2492_(带权并查集)

POj 2492 关系异或
加权并查集

  1. 无法确定bug具体是男还是女,只能知道他们是同性还是异性
  2. 都合并到一个数中,通过边的权值来记录是同性还是异性
  3. 开一个数组rala[]记录点i与点i的父亲节点的关系,1代表性别不同,0代表性别相同
  4. 给出的2点肯定是异性,先判2点断根节点是否一样,相同就通过2点分别推根节点的性别是否一样,一样就正好已经在树中,不一样则不满足教授推论
  5. 根节点不一样就合并根节点,(按照性别关系来合并)
#include <iostream>
#include <string.h>
using namespace std;
const int maxn = 2e4;
int n,m;
int a,b;
int pre[maxn];
int rala[maxn];
void init(int k) {
	memset(rala,0,sizeof rala);
	for (int i=1; i<=k; i++) pre[i] = i;
}
int find(int x) {
	int temp = pre[x];
	if (x==pre[x]) return x;
	pre[x] = find(temp);
	rala[x] = rala[x]^rala[temp];
	return pre[x];
}
void merge(int a,int b) {
	int ra = find(a);
	int rb = find(b);
	if (ra == rb) return;
	
	pre[ra] = rb; // 按规定的顺序来写rala
	rala[ra] = (rala[a] + rala[b] +1)%2; 
}
int cnt;
int main() {
//	freopen("a.txt","r",stdin);
	int scenery ;
	scanf("%d",&scenery);
	while (scenery--) {
		scanf("%d%d",&n,&m);
		init(n); //并查集初始化
		bool flag = true;
		for (int i=1; i<=m; i++) {
			scanf("%d%d",&a,&b);
			// 先判断有没有错误
			int ra = find(a);
			int rb = find(b);
			if (ra == rb) {
				if (rala[a]^rala[b] != 1)
					flag = false; //这里不退出的原因是 要把该组的所有的输入都读取完 
			}
			else { // 根不相同 分别加入到自己的阵营 
				merge(a,b); // 通过find已经使得a,b指向各自根节点,现在判断关系,符合关系则合并根节点. 
			}
		}
		if (flag)
			printf("Scenario #%d:\nNo suspicious bugs found!\n",++cnt); 
		else {
			printf("Scenario #%d:\nSuspicious bugs found!\n",++cnt);
		}
		if (scenery != 0) printf("\n");
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值