并查集——以vijos《家族》为例

并查集可以用来查询两个点是否在同一个集合中,相比于用图dfs,效率大大提升,这里放两个截图对比一下



怎么样,时间差距很大吧!

其实并查集的思想就是找出要合并的点的最大公共祖先,这样我们在判断两个点是不是在同一个集合里只要判断他们的祖先是不是相同就行了。

这里先讲并查集的几个操作:

1:初始化:

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

2:找祖先:

int getf(int v){
	if (f[v]==v){//如果f[v]==v那么就找到当前的祖先了 
		return v;
	}
	else{
		f[v]=getf(f[v]);//如果不是就往上一层节点跳 
		return f[v];//继承祖先 
	}
}

3:合并:

void merge(int v,int u){
	int t1,t2;
	t1=getf(v);
	t2=getf(u);
	if (t1!=t2){
		f[t2]=t1;//这里让左边的祖先成为为右边的祖先
	}
}

完整代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

//定义变量
int n,m,q,f[5005]; 

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

int getf(int v){
	if (f[v]==v){//如果f[v]==v那么就找到当前的祖先了 
		return v;
	}
	else{
		f[v]=getf(f[v]);//如果不是就往上一层节点跳 
		return f[v];//继承祖先 
	}
}

void merge(int v,int u){
	int t1,t2;
	t1=getf(v);
	t2=getf(u);
	if (t1!=t2){
		f[t2]=t1;
	}
}

int main(){
	
	cin>>n>>m>>q;
	int temp_x,temp_y;
	init();//初始化 
	for (int i=1;i<=m;i++){
		cin>>temp_x>>temp_y;
		merge(temp_x,temp_y);
	}
	
	for (int i=1;i<=q;i++){
		cin>>temp_x>>temp_y;
		if (f[getf(temp_x)]==f[getf(temp_y)]){//这里要在找一次father,因为我们在之前合并时可能会没有把某个点的儿子的祖先修改为该节点最远祖先
			cout<<"Yes"<<endl;
		}else{
			cout<<"No"<<endl;
		}
	}
	
	return 0;
	
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值