并查集优化:
路径压缩:
寻找祖先时采用递归,但是一旦元素一多起来,或退化成一条链,每次GetFather都将会使用O(n)的复杂度,这显然不是我们想要的。
对此,我们必须要进行路径压缩,即我们找到最久远的祖先时“顺便”把它的子孙直接连接到它上面。这就是路径压缩了。
Rank合并:
合并时将元素所在深度低的集合合并到元素所在深度高的集合。
#include<stdio.h>
#include<string.h>
#define MAX 100005
int father[MAX],rank[MAX];
int findfather(int a){
if(father[a]==a)
return a;
return father[a]=findfather(father[a]);
}
int Union(int a,int b){
int fa,fb;
fa=findfather(a);
fb=findfather(b);
if(fa==fb) return 0;
if(rank[fa]==rank[fb]){
father[fb]=fa;
rank[fa]++;
}
else if(rank[fa]<rank[fb])
father[fa]=fb;
else
father[fb]=fa;
return 1;
}
int main(){
// freopen("in.txt","r",stdin);
int a,b,i,flag;
while(scanf("%d%d",&a,&b)){
if(a==-1) break;
if(a==0){
printf("Yes\n");
continue;
}
memset(father,0,sizeof(father));
memset(rank,0,sizeof(rank));
flag=0;
do{
if(flag==1) continue;
if(father[a]==0) father[a]=a;
if(father[b]==0) father[b]=b;
if(!Union(a,b)) flag=1;
}while(scanf("%d%d",&a,&b)&&a!=0);
if(flag==1) printf("No\n");
else{
for(i=1;i<MAX;++i)
if(father[i]!=0&&father[i]==i){
if(flag==0) flag=1;
else{
printf("No\n",i);
break;
}
}
if(i==MAX) printf("Yes\n");
}
}
return 0;
}