并查集 (模板)

附上知识博客:并查集

4步走,初始化,查找,合并,路径压缩

1)初始化

for(int i = 0; i < = N; i++){
	father[i] = i;    //也可以为-1
}

2)查找

//递推式 
int findFather(int x){
	while(x != father[x]){
		x = father[x];	
	}
	return x;
}
//递归式 
int findFather(int x){
	if(x == father[x]) return ;
	else return findFather(father[x]);
} 

3)合并

void Union(int a, int b){
	int faA = findFather(a);	//找到a的根节点,记为faA 
	int faB = findFather(b);	//找到b的根节点,记为faB 
	if(faA != faB){		//如果不属于同一个集合 
		father[faA] = faB;	//合并他们 
	}
}

并查集产生的每一个集合都是一棵树

4)压缩路径

上面的并查集没有忧化。

极端情况下效率很低,现在题目给出的元素数量很多,并且形成了一条链,那么这个查找函数的效率会很低,假如说有10^5个元素,那么我们找第一个元素就需要10^5次查询,而且每次查询都需要查询到最后一个元素。每次都需要10^5,这种计算量太难受了,对了我们可以把当前查询结点的路径上的所有节点的父亲都指向根节点

(1)按原先的方法获得x的根节点r

(2)重新从x开始走一遍寻找根节点的过程,把路径上的所有结点的父亲全部改为根节点r。

查找时间就会变成O(1)。有人会说,这样改不消耗时间么?,是的消耗,但是一劳永逸啊。会打表么?

//递推式 
int findFather(int x){
	itn a = x;
	while( x != father[x]){
		x = father[x];
	}
	while( a != father[a] ){	//将从a到 father的路径全指向根节点 
		int z = a;
		a = father[a];
		father[z] = x;
	}
	return x;
}
//递归式 
int findFather(int v){
	if( v == father[v] ) return v;
	else{
		int F = findFather(father[v]);	//递归寻找fagher[v]的根节点 
		father[v] = F;		//将根节点F赋值给father[v] 
		return F;		//返回根节点F 
	}
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值