并查集入门总结

模板

定义

const int N=110;
int father[N];

初始化

for(int i=1;i<=n;i++){//首先让所有的个体都独自称为一个集合
	father[i]=i;
}

查找-递归

int findFather(int x){
	while(x!=father[x]){
		x=father[x];
	}
		return x; 
	}

查找-迭代

int findFather(int x){
	if(x==father[x])return x;
	else return findFather(father[x]);
}

合并

  1. 判断2个元素是否为同一集合
  2. 一个元素的根节点指向另一结点
void Union(int a,int b){
	int faA=findFather(a);
	int faB=findFather(b);
	if(faA!=faB){
		father[faA]=faB;
		}
}

针对查找也可进行路径压缩 后序将补充

例题

n个人 m个好朋友组数

问可以分为几个组

#include <cstdio>
const int N=110;
int father[N]; //存放父亲结点
bool isRoot[N];//是否是同一根结点
int findfather(int x){
    if(x==father[x]) return x;
    else{
        return findfather(father[x]);
    }
}
void Union(int a,int b){
    int faA=findfather(a);
    int faB=findfather(b);
    if(faA!=faB){
        father[faA]=faB;
    }
}
void init(int n){
    for(int i=1;i<=n;i++){
        father[i]=i;
        isRoot[i]=false;
    }
}
int main(){
    int n,m,a,b;
    scanf("%d%d",&n,&m);
    init(n);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&a,&b);
        Union(a,b);
    }
    for(int i=1;i<=n;i++){
        isRoot[findfather(i)]=true;
    }
    int ans=0;
    for(int i=1;i<=n;i++){
        ans+=isRoot[i];
    }
    printf("%d",ans);
    return 0;
}


猜你喜欢

转载自blog.csdn.net/Decmxj1229/article/details/89279803