[算法笔记]带权并查集

带权并查集是普通并查集的进阶版本,功能更加强大。

普通并查集只能判断两个元素是否在一个集合中,带权并查集可以维护集合元素之间的关系,这个关系由每个元素的权值维护。

对权值的维护,我们需要在find(),unite()操作中分别进行修改。

例:399. 除法求值

class UnionFind {
public:
unordered_map<string, string> p;
unordered_map<string, double> d;
UnionFind(vector<vector<string>>& equations, vector<double>& values) {
for (int i = 0; i < values.size(); i++) {
string a = equations[i][0], b = equations[i][1];
// 可能某个结点多次出现,防止对其初始化,导致覆盖
if (!p.count(a)) {
p[a] = a;
d[a] = 1;
}
if (!p.count(b)) {
p[b] = b;
d[b] = 1 ;
}
unite(a, b, values[i]);
}
}
string find(string x) {
if (x != p[x]) {
auto t = find(p[x]);
d[x] *= d[p[x]];
p[x] = t;
}
return p[x];
}
void unite(string a, string b, double v) {
string ra = find(a), rb = find(b);
if (ra != rb) {
p[ra] = rb;
d[ra] = v * d[b] / d[a];
}
}
};

初始化:a, b是两个需要合并的结点,v是它们的值,a,b满足一个关系式,即a/b=v

find():

​ 我们同样进行路径压缩,路径压缩实际上就是将结点x,跳过x的父结点等等,直接与x的根结点相连。普通并查集我们可以直接相连,但是带权并查集我们需要维护结点权值。

​ 如图,a>c的权值就等于a>bb>c,类似于带权有向图,我们要保证a>c的距离不变,换句话说,维护了a>b>c的路径权值和。

unite:

​ 普通并查集中我们只要:

x = find(x), y = find(y);
p[x] = y;

​ 带权并查集中:考虑x/y=v

​ 结点x,y可能有多种情况,可能x==y,  find(x)==x  ||  find(y)==y

​ 我们直接考虑最复杂的情况,即find(x)!!=x  &&  find(y)!=y,这种情况是最复杂的,其他情况都是该情况的特殊情况!

​ 观察图可得,蓝色线代表权值v(蓝色线不会相连,这里只是做出显示),为了维护 四边形法则(也就是X->Y无论从那条路径走,路径权值和应该相等),我们可以求得 Vx=VV2/V1

posted @   macguz  阅读(634)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示