并查集与带权并查集(超清晰)

一.并查集

顾名思义并查集就是用来合并和查询集合的一种数据结构,通常可以达到接近O(1)的时间效率。并查集的实现是通过数组模拟树的结构来实现的。

并查集常用来记录和判断图的连通性问题。

基本原理:每个集合用一棵树来表示,树根(root)的编号就是整个集合的编号。每个节点存储它的父节点(father),p[x]表示x的父节点。
问题1;如何判断树根:if(p[x]==x)
问题2:如何求x的集合编号:while(p[x]!=x) x = p[x]
问题3: 如何合并两个集合:px是x的集合编号,py是y的集合编号,p[x] = y

路径压缩的优化:因为在寻找root时复杂度取决于树的高度。所以可以采用路径压缩。让孙子辈都指向祖宗,减少树的高度。

int find(int x)
{
    if(p[x]!=x) p[x] = find(p[x]);
    return p[x];

}

上面这个函数就是并查集的核心,实现了寻找祖宗和路径压缩的两个功能。

二.带权并查集

在每个树的边上添加一些额外的信息可以更好的处理需要解决的问题,在每条边中记录额外的信息的并查集就是带权并查集。

 这个权值可以根据具体问题具体来定,但是这也带来了一些问题。

首先:每个节点都记录的是与根节点之间的权值,那么在Find的路径压缩过程中,权值也应该做相应的更新,因为在路径压缩之前,每个节点都是与其父节点链接着,那个Value自然也是与其父节点之间的权值。所以要进行权值更新!!!

再者:两个并查集做合并的时候,权值也要做相应的更新,因为两个并查集的根节点不同。

所以我们的find函数变成了这个样子。

int find(int x)
{
    if(p[x] != x)
    {
        int u = find(p[x]);
        value[x] += value[p[x]];
        p[x] = u;
    }
    return  parent[x];
}

首先找到祖宗结点并且记录下来,然后函数递归到完开始退栈的时候,加上每一个结点的权值,最后路径压缩。

合并

		int pa = find(a);
		int pb = find(b);
		if (pa != pb)
		{
			p[pa] = pb;
			value[pa] = 新权值 //具体问题分析
		}

 例如上图:新权值 = s + value[y] - value[x]

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值