并查集——洛谷P3367

题目描述
如题,现在有一个并查集,你需要完成合并和查询操作。

输入输出格式
输入格式:
第一行包含两个整数N、M,表示共有N个元素和M个操作。
接下来M行,每行包含三个整数Zi、Xi、Yi
当Zi=1时,将Xi与Yi所在的集合合并
当Zi=2时,输出Xi与Yi是否在同一集合内,是的话输出Y;否则话输出N

输出格式:
如上,对于每一个Zi=2的操作,都有一行输出,每行包含一个大写字母,为Y或者N
输入输出样例

输入样例#1
4 7
2 1 2
1 1 2
2 1 2
1 3 4
2 1 4
1 2 3
2 1 4
输出样例#1:
N
Y
N
Y

说明
时空限制:1000ms,128M
数据规模:
对于30%的数据,N<=10,M<=20;
对于70%的数据,N<=100,M<=1000;
对于100%的数据,N<=10000,M<=200000。

对于以上这道题,首先我们要知道什么是并查集。并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。那么就涉及到如何并,如何查的问题了。
我们来举个栗子:
a[i]:记录i的祖宗。
father(i):返回i号元素的祖宗。
check(i,j):判断i,j是不是同一个祖宗,是的话返回true,不是返回false。

假如有6个元素,各自为一个集合{1},{2},{3},{4},{5},{6}
初始化:假如我们让每个集合内的元素的祖宗都设为它自己a[1]=1,a[2]=2…a[6]=6
检查:假如我们要将1号元素和2号元素相合并,这时候我们就要判断1号元素和2号元素是不是一个祖宗,如果是,那么他们就已经合并了,如果不是,那么就要开始合并if(check(i,j)==true) 已经是同一个集合不用合并; else 进入下一步合并操作
合并:我们只要将一方的祖宗设置为另一方的祖宗那么就合并成功了,因为我们在检查是否是一个集合的时候,是通过祖宗是否相等来判断的a[father(2)]=father(1)

那么并查集的大概情况我们就很好理解了。下面我们就来贴上例题的代码:

#include<stdio.h>
int N,M;
int a[10001];
int father(int x)
{
	if(a[x]==x)
		return x;
	a[x]=father(a[x]);//路径压缩,以免我们辛辛苦苦找的下次还要找一次 
	return father(a[x]);//如果x的祖宗不是它自己,那么它的祖宗就是它祖宗的祖宗 
}
bool check(int x,int y)
{
	if(father(x)==father(y))
		return true;
	else return false;
}
void merge(int x,int y)//将元素x和y合并到一个集合
{
	if(check(x,y)==false)
		a[father(x)]=father(y);//x的祖宗的祖宗=y的祖宗 
} 
int main()
{
	int x,y,z;
	scanf("%d %d",&N,&M);
	for(int i=1;i<=N;i++)//初始化:每个元素的祖宗都是它本身 
		a[i]=i;
	for(int i=1;i<=M;i++)
	{
		scanf("%d %d %d",&z,&x,&y);
		if(z==1)//合并
			merge(x,y);
		else if(z==2)//查询是否在同一个集合 
		{
			if(check(x,y))
				printf("Y\n");
			else printf("N\n");
		}
		 
	}
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值