Borůvka 算法
定义 $E’$ 为我们当前找到的最小生成森林的边。在算法执行过程中,我们逐步向 $E’$ 加边,定义 连通块 表示一个点集 $V’\subseteq V$ ,且这个点集中的任意两个点 $u$ , $v$ 在 $E’$ 中的边构成的子图上是连通的(互相可达)。
定义一个连通块的 最小边 为它连向其它连通块的边中权值最小的那一条。
初始时, $E’=\varnothing$ ,每个点各自是一个连通块:
- 计算每个点分别属于哪个连通块。将每个连通块都设为“没有最小边”。
- 遍历每条边 $(u, v)$ ,如果 $u$ 和 $v$ 不在同一个连通块,就用这条边的边权分别更新 $u$ 和 $v$ 所在连通块的最小边。
- 如果所有连通块都没有最小边,退出程序,此时的 $E’$ 就是原图最小生成森林的边集。否则,将每个有最小边的连通块的最小边加入 $E’$ ,返回第一步。
当原图连通时,每次迭代连通块数量至少减半,算法只会迭代不超过 $O(\log V)$ 次,而原图不连通时相当于多个子问题,因此算法复杂度是 $O(E\log V)$ 的。给出算法的伪代码:(修改自 维基百科 )
$$
\begin{array}{ll}
1 & \textbf{Input. } \text{A graph }G\text{ whose edges have distinct weights. } \
2 & \textbf{Output. } \text{The minimum spanning forest of }G . \
3 & \textbf{Method. } \
4 & \text{Initialize a forest }F\text{ to be a set of one-vertex trees} \
5 & \textbf{while } \text{True} \
6 & \qquad \text{Find the components of }F\text{ and label each vertex of }G\text{ by its component } \
7 & \qquad \text{Initialize the cheapest edge for each component to “None”} \
8 & \qquad \textbf{for } \text{each edge }(u, v)\text{ of }G \
9 & \qquad\qquad \textbf{if } u\text{ and }v\text{ have different component labels} \
10 & \qquad\qquad\qquad \textbf{if } (u, v)\text{ is cheaper than the cheapest edge for the component of }u \
11 & \qquad\qquad\qquad\qquad\text{ Set }(u, v)\text{ as the cheapest edge for the component of }u \
12 & \qquad\qquad\qquad \textbf{if } (u, v)\text{ is cheaper than the cheapest edge for the component of }v \
13 & \qquad\qquad\qquad\qquad\text{ Set }(u, v)\text{ as the cheapest edge for the component of }v \
14 & \qquad \textbf{if }\text{ all components’cheapest edges are “None”} \
15 & \qquad\qquad \textbf{return } F \
16 & \qquad \textbf{for }\text{ each component whose cheapest edge is not “None”} \
17 & \qquad\qquad\text{ Add its cheapest edge to }F \
\end{array}
$$
转载自 最小生成树 - OI Wiki
Xor-MST
给定一个无向完全图,$i$ 和 $j$ 的边权为 $a_i \oplus a_j$,求最小生成树。
考虑 Borůvka 的过程,最关键的问题是不能枚举边,但是我们只需要知道一个联通块向外的最短边即可,建出字典树查一下。
P.S. 直接按照上述流程实现 Borůvka 算法会超时
代码
1 |
|
Connecting Cities
给定一个无向完全图,$i$ 和 $j$ 的边权为 $D|i-j|+a_i+a_j$,求最小生成树。
类似上述过程,字典树换成线段树。
代码
1 |
|
Tree MST
给定一个无向完全图,$i$ 和 $j$ 的边权为 $dis(i,j)+a_i+a_j$,$dis(i,j)$ 表示树上距离,求最小生成树。
考虑 Borůvka 算法的过程,对于一个点集找出向外的最短边合并。
不妨去掉树上一个点,考虑将每棵子树连向外面的最短边,显然是找一个 $dep_u+a_u$ 最小的点向其他所有点连边。如此递归地处理,即类似点分治的过程。
扣出 $n\log n$ 条关建边后,跑一遍 Kruskal 即可。
代码
1 |
|