并查集

并查集

操作:

1.将两个集合合并

2.询问两个元素是否在一个集合里

一.合并集合

示意图:

并查集问题的关键:

1.如何判断是否是根节点

p[x]=x就是根节点

2.合并两个集合

将x所在集合接在y集合根节点下面

p[find(x)]=find(y)

find函数表示找该集合的根节点

3.路径压缩 

找到根节点的过程中所经过点都指向根节点

 p[x]=find(p[x]);

#include<bits/stdc++.h> 
using namespace std;
const int N=1e5+8;
int p[N];//p[i]表示i的父节点值
int find(int x) {//找x的根结点 
	if(p[x]!=x){
		p[x]=find(p[x]);//压缩路径 
	}
	return p[x];//根 
}
int main(){
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		p[i]=i;//用点的下标值作为父节点
	}
	char op;//操作符
	int x,y; 
	while(m--){
		cin>>op;
		if(op=='M'){
			cin>>x>>y;
			p[find(x)]=find(y);
		}
		else if(op=='Q'){
			cin>>x>>y;
			if(find(x)==find(y)){
				cout<<"Yes"<<endl;
			}
			else {
				cout<<"No"<<endl;
			}
		}
	}
	return 0; 
}

二.连通块中点的个数

考点:

并查集:合并集合

记录每个集合内的点数,用根节点下标表示集合

//并查集 
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+6;
int cnt[N];//表示根节点为i的集合中结点数
int p[N];//p[i]表示i结点的父节点
//并查集算法 
//找根节点 
int find(int x) {
	//递归
	if(p[x]!=x) {
		p[x]=find(p[x]) ;
	}
	return p[x];
}

int main(){
	int n,m;
	cin>>n>>m;
    //开始每个点是单独的集合
	for(int i=1;i<=n;i++){
		p[i]=i;
		cnt[i]=1;
	}
	string op;
	int x,y;
	while(m--){
		cin>>op;
		if(op=="C"){
			cin>>x>>y;
			int a=find(x);
			int b=find(y);
			if(a!=b){
				p[a]=b;
				cnt[b]+=cnt[a];
			}
		}
		else if(op=="Q1"){
			cin>>x>>y;
			if(find(x)==find(y)){
				cout<<"Yes"<<endl;
			}
			else{
				cout<<"No"<<endl;
			}
		}
		else if(op=="Q2"){
			cin>>x;
			cout<<cnt[find(x)]<<endl;//要先找到该集合的根节点,然后由根节点查询当前集合的点数
		}
	}
	return 0;
}

 

posted @ 2025-02-03 08:17  Annaprincess  阅读(4)  评论(0)    收藏  举报