//得先加集合个数再合并!!!!!!!!!
核心代码:
int find(int x){
//返回父节点
if(x != p[x]) {
p[x] = find(p[x]);//路径压缩
} //孩子不等于爸爸,就找爸爸的爸爸
return p[x];
}
题目链接:836 合并集合
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
int n,m;
int p[100010];
void init(){
for(int i=1;i<=100010;i++){
p[i] = i;
}
}
int find(int x){
//返回父节点
if(x != p[x]) {
p[x] = find(p[x]);//路径压缩
} //孩子不等于爸爸,就找爸爸的爸爸
return p[x];
}
int main()
{
init();
scanf("%d%d",&n,&m);
//for(int i=1;i<=n;i++){
// p[i] = i;
//}
while(m--){
char op[2];
int a,b;
scanf("%s%d%d",&op,&a,&b);
if(op[0] == 'M'){
p[find(a)] = find(b);
// int f1 = find(a);
// int f2 = find(b);
// printf("ffff%d %d\n",f1,f2);
// if(f1 == f2) continue;
// else{
// p[f1] = f2;
// }
}
else{
if(find(a) == find(b))
printf("Yes\n");
else{
printf("No\n");
}
}
}
return 0;
}
题目链接:837. 连通块中点的数量
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
int n,m;
int p[100010];
int size1[100010];//连通块里的个数,只保证根节点的size有意义
int find(int x){
//返回父节点
if(x != p[x]) {
p[x] = find(p[x]);//路径压缩
} //孩子不等于爸爸,就找爸爸的爸爸
return p[x];
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
p[i] = i;
size1[i] = 1;
}
getchar();
while(m--){
char op[5];
int a,b;
scanf("%s",&op);
if(op[0] == 'C'){
scanf("%d%d",&a,&b);
if(find(a) == find(b)) continue;
//得先加集合个数再合并!!!!!!!!!
size1[find(b)] += size1[find(a)];
p[find(a)] = find(b);
}
else if(op[1] == '1')
{
scanf("%d%d",&a,&b);
if(find(a) == find(b))
printf("Yes\n");
else{
printf("No\n");
}
}
else{
//求连通块的数量,先找父节点
scanf("%d",&a);
printf("%d\n",size1[find(a)]);
}
}
return 0;
}