带权并查集(种类并查集)的简单总结(顺带总结并查集)

并查集是一种树型的数据结构,一般用于处理一些不相交集合(Disjoint Sets)的合并及查询问题,对于普通的并查集我们一般分为三个部分——初始化,查找,合并。

初始化:把每个点所在集合初始化为其自身(即每个元素单独构成一个集合,其父结点是其本身)。

查找:查找元素所在的集合,即根节点。

合并:将两个元素所在的集合合并为一个集合(注:当我们想对两个元素进行合并时,那么必然时它们之间存在某种关系。在进行合并前,我们首先需要进行一次判断,判断这两个元素是否已经在同一个集合了,若是已经在同一个集合则没必要重复合并,若不是在同一个集合则需要合并,通常我们判断两个元素是否在同一个集合是通过查找操作查找这两个元素的父节点,若两个元素的父节点一致则是在同一集合,反之不然)

直接贴上各部分的代码吧。

初始化:

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

查找:

int find(int v){
	if(f[v]==v)return f[v];
	f[v]=find(f[v]);//路径压缩
	return f[v];
}

路径压缩可能稍微有点难理解。其实当我们在寻找祖宗节点时,会遇到两种情况

第一种情况:                                                                                         第二种情况:

                                   

显然,当我们遇到的是第一种情况的时候,其父节点就是其祖宗节点(根节点),这种情况路径压缩显然是很没有用处的,不过当我们遇到第二种情况的时候,我们找寻的是x的祖宗节点(根节点),在找寻的过程中,我们发现x有许多的长辈,这些长辈的祖宗节点和x的祖宗节点是同一个,那么我们为了节省以后找这些长辈节点的祖宗节点的时间,我们直接在找x的祖宗节点的同时顺带找到这些长辈节点的祖宗节点(因为他们的祖宗节点是同一个),在进行完这些操作(路径压缩)之后,上面的第二个图就变成了下面这个图了。

当我们将一条长链上的所有节点都与根节点直接相连时(菊花图),下一次我们对这条链上任意一个节点进行查找时,时间复杂度都是O(1)(没有进行再合并的情况下),这无疑大大节省了我们查找的时间。

合并:

void merge(int x,int y){
	int t1,t2;
	t1=find(x);
	t2=find(y);
	if(t1!=t2){
		f[t2]=t1;
	}
	return;
}

其实带权并查集也只有这三个部分,不过带权并查集与普通并查集不同的是带权并查集比普通并查集多了一个需要考虑的东西——权值。这个权值其实也可以说是一种关系,比如x比y高10分,这就是一种关系,凡是有性质上相同的关系的点我们都应该把他们归为一个集合。好了,现在来一个问题,假如x比y高10分,y比z高5分的话,x与z之间的关系是什么,x比z高多少分?很显而易见,x比z高15分,这是小学生都会的题目,虽然简单,不过我们可以借这个题来帮助我们理解带权并查集点和点之间的关系。我们将他们之间的关系转化为图,如下:

我们不难发现他们之间的关系其实可以转化成x->z=x->y+y->z,有些人可能不理解,为什么会得到这样一个公式,这样的公式能推广到有很多点的情况吗?这些问题相信看完下面这张图你会得到一个结论的。

啊哈!发现新大陆了吧,没错,其实呢,带权并查集点和点之间的关系就类似于我们数学上所学的向量,不管起点到终点的路径是怎么样的,只要我们的起点和终点是一样的,那么位移就必定相等。

在明白这一点之后,我们再来思考一下,如果x比z高5分,y比z高10分的话,x和y又是什么关系勒?这个我就不画了,你们自己好好动手画一下看能得出什么样的结果吧。

画完之后直接来个经典的例题吧。

HDU-3038 How Many Answers Are Wrong

题目链接http://acm.hust.edu.cn/vjudge/contest/view.action?cid=66964#problem/D

--------------------------------------------------------------------未完待续--------------------------------------------------------------------------

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值