题意:
如题,现在有一个并查集,你需要完成合并和查询操作。
分析:
开始学习并查集。并查集有两种方式优化:按秩合并、路径压缩。按秩合并中的秩指的是树的深度,即总是将更小的树连接至更大的树上。而路径压缩是一种在执行“查找”时扁平化树结构的方法。关键在于在路径上的每个节点都可以直接连接到根上。
代码(只按秩合并):
#include<bits/stdc++.h>
using namespace std;
int father[10010],R[10010];
//建立一个新的集合,每一个子节点就是一个数,本身就是他的根节点
void Make_Set(int x){
father[x] = x; //根节点
R[x] = 0; //秩大小
}
//通过递归向上查找根节点,回溯时改变当前节点的父节点,直接指向根节点。
int Find_Set(int x){
if(x != father[x])
father[x] = Find_Set(father[x]);
return father[x];
}
//两个集合的合并算法
void Union(int x, int y){
int GrandX = Find_Set(x);
int GrandY = Find_Set(y);
if(GrandX == GrandY)
return;
if(R[GrandX] < R[GrandY])
father[GrandX] = GrandY;
else{
if(R[GrandX] == R[GrandY])
R[GrandX]++;
father[GrandY] = GrandX;
}
}
int main(){
int n,m,z,x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
Make_Set(i);
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&z,&x,&y);
if(z==1){
Union(x,y);
}else{
if(Find_Set(x)==Find_Set(y))
printf("Y\n");
else
printf("N\n");
}
}
return 0;
}
代码(再经过路径压缩优化):
#include<bits/stdc++.h>
using namespace std;
int father[10010],R[10010];
//建立一个新的集合,每一个子节点就是一个数,本身就是他的根节点
void Make_Set(int x){
father[x] = x; //根节点
R[x] = 0; //秩大小
}
//查找的同时进行路径压缩。
int Find_Set(int x){
while(x != father[x]){
father[x]=father[father[x]];
x=father[x];
}
return x;
}
//两个集合的合并算法
void Union(int x, int y){
int GrandX = Find_Set(x);
int GrandY = Find_Set(y);
if(GrandX == GrandY)
return;
if(R[GrandX] < R[GrandY])
father[GrandX] = GrandY;
else{
if(R[GrandX] == R[GrandY])
R[GrandX]++;
father[GrandY] = GrandX;
}
}
int main(){
int n,m,z,x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
Make_Set(i);
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&z,&x,&y);
if(z==1){
Union(x,y);
}else{
if(Find_Set(x)==Find_Set(y))
printf("Y\n");
else
printf("N\n");
}
}
return 0;
}