1.初始化
2.find()函数的实现(查找)
3.join()函数的实现(合并)
1.将所有人的boss(祖先节点)设定为自己
code↓
for(int i=1;i<=n;i++) pre[i]=i;
1.不断的向上查找自己的boss(员工->经理->CEO->董事长[boss])
在这里面:
find(员工)=董事长,find(经理)=董事长
find(CEO)=董事长,find(董事长)=董事长
但是我们在存储
时,是这样的:
pre[员工]=经理,pre[经理]=CEO
pre[CEO]=董事长,pre[董事长]=董事长
如果我们直接去用while查找
是这样的
code↓
while(pre[x]!=x)//如果x不是自己的boss就运行,如果是那就结束。
x=pre[x];//继续进行查找,不断进行复制
return x;//返回最后的结果
/*
a[1] a[2] a[3] a[4] a[5]
2 3 4 5 5
这个循环的解释
是怎样的↓
假设我们的x=2;
x=2,a[x]不等于自己,于是x=a[2],x=3;
x=3,a[x]不等于自己,于是x=a[3],x=3;
x=4,a[x]不等于自己,于是x=a[4],x=3;
x=5,a[x]等于自己,于是终止循环,return x;
这种做法有优点也有缺点:
1.优点是可以进行回溯
2.缺点是需要的时间复杂度
太高,会TLE
如果我们要进行优化,就需要使用路径压缩
和递归
1.并查集的路径压缩
,就是直接将每个人都指向它的boss
pre[员工]=董事长,pre[经理]=董事长
pre[CEO]=董事长,pre[董事长]=董事长
code↓
return pre[x]=find(pre[x]);
2.而我们使用递归就需要一个退出语句
,也就是当自己是自己的boss
时退出。
code↓
if(pre[x]==x) return x;
总结起来find()函数就是这样的
code↓
int find(int x){
if(pre[x]==x) return x;
else return pre[x]=find(pre[x]);
}
如果需要将代码压缩就是这样的
code↓
int find(int x){
return x == pre[x] ? x : (pre[x] = find(pre[x]));
}//如果(x==fa[x])=ture return x,否则 return (pre[x] = find(pre[x]))
1.优点是时间复杂度
低
2.缺点是不能回溯
,第一次进行查找没有压缩效果
。
1.将两个员工(节点)的boss(祖先)合并在一起:
设:有2个boss,分别为a,b
合并操作就是将a的boss改为b,或将b的boss改为a
1.给定的是两个员工(节点),要先求出他们的boss(祖先)
code↓
int a=find(x);//a是x的boss
int b=find(y);//b是y的boss
2.接下来,我们需要分成两种情况进行讨论
当a=b时,说明了他们的boss是同一个人,不需要进行合并
只有当a!=b时,他们的boss不同,需要进行合并
code↓
if(a!=b){//如果x的boss不是y的boss,进行合并
pre[find(b)]=find(a);//多进行一次查找,确定是哪一个boss
}
3.函数的末尾return 0;
code↓
int join(int x,int y){
int a=find(x);
int b=find(y);
if(a!=b){
pre[find(b)]=find(a);
}
return 0;
}
code↓
int find(int x){
if(pre[x]==x) return x;
else return pre[x]=find(pre[x]);
}
int join(int x,int y){
int a=find(x);
int b=find(y);
if(a!=b){
pre[find(b)]=find(a);
}
return 0;
}
code↓
#include
using namespace std;
int pre[200050]={};
int z,x,y;
int find(int x){
if(pre[x]==x) return x;
else return pre[x]=find(pre[x]);
}
int join(int x,int y){
int a=find(x);
int b=find(y);
if(a!=b){
pre[find(b)]=find(a);
}
return 0;
}
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) pre[i]=i;
for(int i=1;i<=m;i++){
cin>>z>>x>>y;
if(z==2)
if(find(x)==find(y)) cout<<"Y"<<endl;
else cout<<"N"<<endl;
if(z==1) join(x,y);
}
return 0;
}