POJ2492 并查集的高级应用

题意:一群臭虫的脑残生活,告诉你臭虫之间的交配关系,问里面是否有gay或les。

 

用并查集来做

Set数组保存集合或父亲节点,Rel数组保存该元素与父亲节点的关系。

 

每告诉你一对关系,先判断是否在同一集合中,如果不在,则合并两个元素所在的集合,若在同一个集合中,则判断两者是否有不正当的关系。

 

关系的相互转化:运用到离散数学中二元关系方面的知识   a-c=a-b ^ b-c  例如:a-b的关系是1,b-c的关系是1,则a-c的关系是0

关系的转化在两个情况下进行,1.并查集的路径压缩优化时进行转化。2.合并两个集合时,确定两个集合的关系时需要转化。

 

合并时因为已经进行了路径压缩,则有A-B = A-a ^ a-b ^ b-B    由于关系^可逆 所有A-a = a-A

 

#include<stdio.h>

int Set[2001],Rel[2001];
int Case,N,M,Flag,TT;

int Find(int a){
	int root;
	if(Set[a]!=a){
		root=Find(Set[a]);
		Rel[a]=Rel[a]^Rel[Set[a]];
		Set[a]=root;
		return root;
	}
	return a;	
}

void UnionSet(int a,int b){
	int A,B;
	A=Find(a);
	B=Find(b);
	if(A!=B){
		Set[A]=B;
		Rel[A]=Rel[a]^1^Rel[b];
	}
}

void Judge(int a,int b){
	if(Rel[a]==Rel[b])
		Flag=1;
}

int main(){
	int i,a,b,A,B;
	scanf("%d",&Case);
	TT=1;
	while(TT<=Case){
		Flag=0;
		memset(Rel,0,sizeof(Rel));
		scanf("%d %d",&N,&M);
		for(i=1;i<=N;i++)
			Set[i]=i;
		for(i=1;i<=M;i++){
			scanf("%d %d",&a,&b);
			if(Flag) continue;
			A=Find(a);
			B=Find(b);
			if(A!=B)
				UnionSet(a,b);
			else 
				Judge(a,b);
		}
		printf("Scenario #%d:\n",TT);
		if(Flag)
			printf("Suspicious bugs found!\n\n");
		else 
			printf("No suspicious bugs found!\n\n");
		TT++;
	}
	return 0;
}
 


 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值