目录
模板
1.初始化
void init(){//初始化集合号
for(int i=1;i<=n;i++)
fa[i]=i; //把节点i的集合号初始化为自身
}
2.查找
int Find(int x){ //查找
if(x!=fa[x])
fa[x]=Find(fa[x]);
return fa[x];
}
3.合并
void Union(iont x,int y){ //合并
int a=Find(x);
int b=Find(y);
if(a!=b)
fa[b]=a;
}
题目
1.畅通工程
for(int i=1;i<=n;i++)
fa[i]=i; //初始化集合号为自身‘
for(int i=0;i<m;i++){
scanf("%d%d",&x,&y);
Union(x,y);
}
for(int i=1;i<=n;i++){
if(i==fa[i])
ans++;
}
printf("%d",ans-1);//记得减1
2.帮派
思路
划分为不同集合的方法:可以给每一个节点x都复制一个影子x+n,将x,y划分为不同的集合,只需将x和y的影子合并为一个集合,并将x+n和y合并为一个集合
//初始化
void init(){
for(int i=1;i<=2*n;i++){
fa[i]=i;
h[i]=0;
}
}
//查找集合号
int Find(int x){
if(x!=fa[x])
fa[x]=Find(fa[x]);
return fa[x];
}
//合并
void Union(int x,int y){
int a=Find(x);
int b=Find(y);
if(a==b)
return;
if(h[a]>h[b]) //启发式合并,把矮树合并到高树之下
fa[b]=a;
else{
fa[a]=b;
if(h[a]==h[b])
h[b]++;
}
}
//判定结果
while(m--){
char ch[2];
int x,y;
scanf("%s%d%d",ch,&x,&y);
if(ch[0]=='D'){
Union(x,y+n);
Union(x+n,y);
}
else{
if(Find(y+n)==Find(x)||Find(x+n)==Find(y))
printf("in different gangs");
else if(Find(y)==Find(x)||Find(x+n)==Find(y+n))
printf("in the same gang");
else
printf("not sure");
}
}