算法标签 并查集

题目简叙

[Acwing]836. 合并集合_父节点

思路

并查集:
1.将两个集合合并
2.查询两个元素是否在同一个元素当中

基本原理:每个集合用一颗树来表示,树根的编号就是当前集合的编号。每个节点存储它的父节点,p[x]表示x的父节点

问题1;:如何判断树根:if(p[x]==x)
这里非常重要的是:我们从一开始把所有p[x]=x了,这样一来,就可以用p[x]==x来判断是否是一个树的根节点
问题2:如何求X的集合编号:while(p[x]!=x)x=p[x];
如果不是根节点,就一直指向下一个,直到指向根节点为止
问题3:如何合并两个集合:p[find(a)]=find(b);
直接把一个树的根节点指向到另一个根节点即可

如图

[Acwing]836. 合并集合_父节点_02

代码

#include<iostream>

using namespace std;

int n,m;
const int N=1e5+10;
int p[N];//存储指向

int find(int n){
if(p[n]!=n)p[n]=find(p[n]);//如果父节点不是初始化的且不是一个树根,那么就指向祖父节点,知道指向一个树根为止,同时路径上的所有节点都指向了根节点
return p[n];//返回
}
int main(){
cin>>n>>m;

for(int i=0;i<n;i++)p[i]=i;//初始化,一共n个数字初始化有n个集合

string op;//操作符
int a,b;
while(m--){
cin>>op;
cin>>a>>b;
if(op[0]=='M'){
p[find(a)]=find(b);//a的祖父节点,指向b的祖父节点,相当于集合a合并到集合b之中
}
else {
if(find(a)==find(b))cout<<"Yes";//如果指向的节点相同,证明在同一集合
else cout<<"No";
cout<<endl;
}
}

return 0;
}

AC记录

[Acwing]836. 合并集合_父节点_03