算法标签 并查集
题目简叙
思路
合并集合的变体
一、初始化
for(int i=0;i<n;i++)p[i]=i,cnt[i]=1;
p[i]=i表示这是一个树根,一个祖节点
cnt[i]=1表示是这个集合初始化只有它一个元素
二、找根节点
int find(int x){
if(p[x]!=x)p[x]=find(p[x]);
return p[x];
}
三、合并连通块
if(op=="C"){
cin>>a>>b;
a=find(a),b=find(b);
if(a!=b){
p[a]=b;
cnt[b]+=cnt[a];
}
}
如果两个元素不在同一个集合
那么a的祖节点指向b的祖节点,合并两个集合
b的联通块数量等于两者之和
四、询问是否连通
if(find(a)==find(b))cout<<"Yes"<<endl;
else cout<<"No"<<endl;
五、联通块数量
cin>>a;
cout<<cnt[find(a)]<<endl;
返回整个集合有多少个元素
代码
#include<iostream>
using namespace std;
const int N=1e5+10;
int cnt[N],p[N];
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=0;i<n;i++)p[i]=i,cnt[i]=1;
string op;
int a,b;
while(m--){
cin>>op;
if(op=="C"){
cin>>a>>b;
a=find(a),b=find(b);
if(a!=b){
p[a]=b;
cnt[b]+=cnt[a];
}
}
else if(op=="Q1"){
cin>>a>>b;
if(find(a)==find(b))cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
else {
cin>>a;
cout<<cnt[find(a)]<<endl;
}
}
return 0;
}