并查集题解

1526【并查集模板题】ubiquitous religion

链接

poj -1182食物链

链接 链接

并查集可以用于表示同一类事物,这里除了表示A,B,C三类,还需要表示三者之间的关系。

考虑将并查集数组扩大成3*N, 对于 bin[x] 表示和x同一类的,且是x的父节点,对于bin[x+N]表示是x吃的那一类的,bin[x+2 *N]表示是吃x的那一类的。

  • 输入1 x y时,若先前x和y不是同一类,则错误++,否则合并成同一类(此时x和y, x+N和y+N,x+2* N和y+2* N分别都要合并成一类。

  • 输入 2 x y 若先前x和y的关系不是x吃 y,错误++,否则构造x吃y的关系(将x和y+2*N, x+N和y,x+2 * N和y+N合并成一类)

#include<iostream>
#include<cstdio>

using namespace std;

const int N=50001;

//poj上的这题输入输出必须用scanf,printf,用cin会超时。
//openjudge可以使用cin,cout。 

//bin[i]是i的同类(的下标)    A
//bin[i+n]表示和i吃的是同类,存的是被i吃的某个动物的下标  B 
//bin[i+2*n]表示和吃i的是同类   C

int bin[3*N];
int n,k;	 

//在poj上会TLE,尝试路径压缩,压不压缩不是关键问题。(cin,cout才是) 
int find(int x){
	int r=x;
	while(r!=bin[r])
		r=bin[r];
//	while(x!=bin[x]){
//		int y=x;
//		x=bin[x];
//		bin[y]=r;
//	}
	return r;
}

void merge(int x,int y){
	int fx=find(x),fy=find(y);
	if(fx==fy) return;
	else {
		bin[fy]=fx;
	}
}

void init(){
	for(int i=1;i<=3*n;i++)
		bin[i]=i;
}

bool same(int a,int b){ //判断是不是同一类 
	int fa=find(a);
	int fb=find(b);
	if(fa==fb) return true;
	else return false;
}

int main(){
	
	int resnum=0;
	scanf("%d%d",&n,&k);
	init();
	for(int i=0;i<k;i++){
		int d,x,y;
		scanf("%d%d%d",&d,&x,&y);
		if(x>n||x<=0||y>n||y<=0) resnum++;
		else if(d==1){
			//这里拿same(y,x+n)这种条件来判断是一样的 
			if(same(x,y+n)||same(x,y+2*n)) resnum++;
			else{
				merge(x,y);   //x和y是同类,则吃x的和吃y的也是同类 
				merge(x+n,y+n);
				merge(x+2*n,y+2*n);
			}
		}
		else if(d==2){  //x吃y 
			if(x==y) resnum++;
			else{
	//这里的判断和挑战书上有些出入,因为我对bin[y+n]等的定义是按照开头定义来的,但也能过 
				if(same(x,y)||same(x,y+n)) resnum++;  //若不是x吃y的关系,错误++
				else{
					merge(x,y+2*n);   //此出体现A->B,B->C,C->A这种环形关系 
					merge(x+n,y);
					merge(x+2*n,y+n); //x被 y吃的类 吃 
				}
			}
		}
	}
	
	printf("%d",resnum); 
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值