[英]union find disjoint set weighted quick union with path compression algorithm
[英]Application of Union+Find algorithm(Disjoint Set)
问题陈述:
方程以A / B = k
的形式给出,其中A
和B
是表示为字符串的变量,而k
是实数(浮点数)。
给定一些查询,返回答案。 如果答案不存在,则返回-1.0。
示例:给定a / b = 2.0, b / c = 3.0.
查询是: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ?
返回[6.0, 0.5, -1.0, 1.0, -1.0 ]
输入为:
vector<pair<string, string>> equations
vector<double>& values
vector<pair<string, string>> queries
其中equations.size() == values.size()
,并且值是正数。
这表示方程式。
返回vector<double>
。
根据上面的示例:equations = [ ["a", "b"], ["b", "c"] ]
值= [2.0, 3.0]
查询= [ ["a", "c"], ["b", "a"], ["a", "e"], ["a", "a"], ["x", "x"] ]
输入始终有效。 您可以假设对查询进行评估将不会导致被零除,并且没有矛盾。
解决方案这可以通过对不交集使用Union + Find来解决,在这里可以看到一个解决方案:
但是,我不清楚第59行背后的直觉:
rst[i] = uf.rank.get(queries[i][0]) / uf.rank.get(queries[i][1]);
以及第99行:
rank.put(aFather, quotient * rank.get(b) / rank.get(a));
不难理解会发生什么。 其实很聪明!
让我们举一个更复杂的例子:
a / b = 2.0, b / c = 3.0, c / d = 4.0, d / e = 5.0
在第一步骤(MakeSet触发由UnionFind uf = new UnionFind(set)
)的每个元素设定为它自己的父,并且所有等级被设置为1.0:
parent(a) = a, rank(a) = 1.0
...
parent(e) = e, rank(e) = 1.0
在联盟步骤中,节点的等级被设置为给定商数,而父的等级保持不变(线99)。 因此,在union(a, b, 2.0) parent(a) = b, rank(a) = 2.0
并为任何节点n保持不变: rank(n)/rank(parent(n)) = value
,其中value来自正在处理的方程式( quotient
参数)。 最后,我们得到:
parent(a) = b, rank(a) = 2.0
parent(b) = c, rank(b) = 3.0
parent(c) = d, rank(c) = 4.0
parent(d) = e, rank(d) = 5.0
parent(e) = e, rank(e) = 1.0
在“ 压缩”步骤中,如果要搜索的节点的父级不是集合的代表节点 ,则通过递归搜索该父级的父级的父级并设置当前节点的等级来将其设置为节点作为当前等级乘以父级的等级(第87行)。 所以最后我们得出:
parent(a) = e, rank(a) = 120.0
parent(b) = e, rank(b) = 60.0
parent(c) = e, rank(c) = 20.0
parent(d) = e, rank(d) = 5.0
parent(e) = e, rank(e) = 1.0
因此,实际上,正如输入方程式中给出的那样,等级(a)=等级(b)* 2.0,等级(b)=等级(c)* 3.0等。
请注意,集合的代表节点 (即最终父节点,在此示例中为e
)始终以1.0排名结束。 这就是为什么一旦计算出节点并设置了父节点后,重复调用compressedFind
并执行第87行就不会进一步更改节点的等级的原因。
现在很容易看到第59行的工作方式:如果查询是a / b,则rank(a)/ rank(b)= 120.0 / 60.0 = 2.0
从这里使用的术语: https : //en.wikipedia.org/wiki/Disjoint-set_data_structure
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.