并查集模板及其优化

基本模板

int f[10000];
void init(int n){
	for(int i=1;i<=n;i++)
		f[i]=i;
}

//非递归
int getf(int a) {
    int root = a;
    while (f[root] != root)
        root = f[root];
    int tmp;
    while (a != root) {
        tmp = f[a];
        f[a] = root;
        a = tmp;
    }
    return root;
}

//递归
int getf(int a){
	if(f[a]==a)return a;
	else return f[a]=getf(f[a]);
}

void merge(int a, int b) {
    a = getf(a);
    b = getf(b);
    if (a != b) {
        f[b] = a;
    }
}

bool same(int a,int b){
	return getf(a)==getf(b);
}

并查集的优化

int f[10000];
int rank[10000];//存储树的高度

void init(int n){
	for(int i=0;i<n;i++){
		f[i]=i;
		rank[i]=0;
	}
}	

int getf(int a){
	if(f[a]==a)return a;
	else return f[a]=getf(f[a]);
}

void merge(int a,int b){//主要是这里的优化
	a=getf(f[a]);
	b=getf(f[b]);
	if(a==b)return;
	if(rank[a]<rank[b]){
		f[a]=b;
	}else{
		f[b]=a;
		//若两棵树原本一样高,则高度会增加
		if(rank[a]==rank[b]) rank[a]++;
	}
}

并查集删除

  • 首先每个节点不再指向自己而是另一个比不会出现的节点,类似于将每个节点放到一个盒子中
  • 这样,删除时只需要把这个节点从当前盒子拿出来,放到另一个盒子中
  • 由于节点之间都是通过盒子来确定关系的,所以盒子中元素是否存在并不影响节点之间的关系
int index;   //存放盒子节点使用到哪一个了
int f[22222];
void init(int n)
{
    index = n+1;
    for(int i=1;i<=n;i++)     //普通节点指向他的盒子节点
        f[i] = index++;
    for(int i=n+1;i<=2*n;i++)   //盒子节点指向自己就像一般的并查集一样
        f[i] = i;
}
 
void del(int n)
{
    f[n] = index;   //将要删除的节点重新指向一个新的盒子
    f[index] = index++ ;   //盒子节点指向自己
}

int getf(int a){
	if(f[a]==a)return a;
	else return f[a]=getf(f[a]);
}

void merge(int a, int b) {
    a = getf(a);
    b = getf(b);
    if (a != b) {
        f[b] = a;
    }
}

注意:这种方法要保证空间足够大,不然会出错。

应用

  1. 判断图是否联通。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值