并查集详解及模板

          并查集,在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。这一类问题近几年来反复出现在信息学的国际国内赛题中,其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题需要的结果,只能用并查集来描述。 (摘自百度)

 

关于并查集和路径压缩:

有a,b,c三个人,假设a和b打架了,a做了b的小弟。则令f[a]=b;   后来a打赢了c,那么c就是a的小弟了。所以,令f[c]=a;

但是,c不知道b,这不符合要求,也不符合规律。所以,我们必须让c的大哥变成最大的老大。

int find(int k){
    if(f[k]==k)return k;
    return find(f[k]);
}

f[c]=find(a);

这时,我们可以使途中经过的人的大哥也变成老大。

//路径压缩
int find(int k){
    if(f[k]==k)return k;
    return f[k]=find(f[k]);
}

f[c]=find(a);

 ACM一行代码。QAQ

int find(int x){return f[x]==x?x:(f[x]=find(f[x]));}

 

而判定a,b 两个人的老大是否相等,只需用

if(find(a)==find(b))

题目:P3367 【模板】并查集

#include<iostream>
using namespace std;
int n,m,p1,p2,p3,k;
int f[10005];

int find(int k)
{
	if(f[k]==k)return k;
	return f[k]=find(f[k]);
}
int main()
{
	
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		f[i]=i;              //初始化将其定为自己 
	}
	while(m--)
	{
		cin>>p1>>p2>>p3;
		if(p1==1)
		{
			f[find(p2)]=find(p3);
			//p3定为老大 
		}
		else
		{
			if(find(p2)==find(p3))
			{
				cout<<"Y"<<endl;
			}
			else
			{
				cout<<"N"<<endl;
			}
		}
	}
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值