最小生成树与 Kruskal 重构树

基本概念

对于有限可重集 \(S\),称 \(S\) 中最大的数为 \(S\)瓶颈.(视语境不同也可指最小的数.)有限可重集之间可以定义大小关系:将元素分别从小到大排序,得到一个权值序列,按序列的字典序比较可重集的大小.

对于无向带权连通图 \(G\),若 \(G\) 的一个无环连通子图 \(T\) 包含 \(G\) 的所有顶点,则称 \(T\)\(G\) 的一个生成树. \(T\) 的边权总和称作生成树的大小\(T\) 的边权瓶颈称作生成树的瓶颈\(T\) 的边权从小到大排序后得到生成树的边权序列. 对某个图 \(G\),所有生成树中最小的称作最小生成树,瓶颈最小的称作最小瓶颈生成树,边权序列字典序最小的称作最小字典序生成树.

一般地,对于无向带权图 \(G\)(不一定连通),也可定义相应的生成森林.

最小字典序生成树

对于图 \(G\),设生成树 \(T\) 的边权序列为 \(\{t_i\}\),最小字典序生成树 \(M\) 的边权序列为 \(\{m_i\}\),则 \(\{m_i\}\) 的字典序小于等于 \(\{t_i\}\) 的字典序. 事实上我们有更强的结论:\(\{m_i\}\) 的每个位置都小于等于 \(\{t_i\}\)于是能够推出,对任意 \(k\)\(M\) 让第 \(k\) 大的边取到了最小. 特别地,\(M\) 让最大的边取到了最小,也就是说,最小字典序生成树都是最小瓶颈生成树. 另外,既然每条边都取到了最小,最小字典序生成树也是最小生成树.(同时最小生成树都是最小字典序生成树,因此这两种生成树等价;这也说明所有最小生成树的边权序列都相同.)

下面我们来证明这个结论. 用反证法,设某个 \(i\) 能使 \(m_i>t_i\). 现在在 \(M\) 中只保留前 \(i-1\) 条边(记为 \(M'\)),这会形成 \(n-i+1\) 个连通块(\(n\) 为点数),将图 \(G\) 划分成 \(n-i+1\) 个点集. 在 \(T\)\(n-1\) 条边中,至少要有 \(n-i\) 条边是“跨点集”的(不然 \(T\) 不连通了),根据抽屉原理,至少有一条边是 \(t_1,t_2,\cdots,t_i\) 之一(因为其他的边只有 \(n-1-i\) 条),设它是 \(t_j\ (1\le j\le i)\). 现在把 \(t_j\) 加进 \(M\),这会在 \(M\) 中形成一个环. 由于 \(t_j\) 是“跨点集”的(即 \(t_j\) 的两个端点在 \(M'\) 中不连通),环上至少有一条边不属于 \(M'\),不妨设它是 \(m_k\),这里我们有 \(i\le k\le n-1\). 因为 \(\{t_i\}\)\(\{m_i\}\) 都是升序,有 \(t_j\le t_i<m_i\le m_k\). 于是只要把 \(m_k\) 删掉,就把 \(M\) 改造成了一棵字典序更小的生成树,这就导出了矛盾.

Kruskal 算法

给定图 \(G\),我们用贪心法求解 \(G\) 的最小字典序生成树. 首先把 \(G\) 中所有边权从小到大排序,依次将这些边加入生成树中. 对于某一条边 \((u,v,w)\),若加入之后不形成环(即加入前 \(u\)\(v\) 不连通)则加入,否则跳过. 可用并查集维护连通性. 时间复杂度 \(O(m\log m)\),其中 \(m\) 为边数.

这样贪心有一点小问题:如果存在相等的边权,它们加入的先后顺序如何确定呢?事实上,相等的边权无论按什么顺序加入,最后都会得到一棵最小字典序生成树. 这很容易证明:考虑我们即将加入一批边权为 \(c\) 的边. 加入前的图 \(G\) 可能已经连了一些边,我们把每个连通块都看作一个点;考察全体 \(c\),忽略在连通块内部的边(缩点后相当于自环),我们先把其他 \(c\) 都加入 \(G\),然后取新 \(G\) 的一个生成森林即可. 显然,取的边数是确定的. 另外,加入后新形成的连通块会在下一批边加入前缩掉,所以取哪个生成森林对之后的连通性没有影响.

这段分析是重要的. 我们在矩阵树定理的相关问题中还会见到它.

这便是最小生成树的 Kruskal 算法.

最小瓶颈路

对于图 \(G\) 上的一条路径,可定义它的瓶颈为边权的瓶颈(本文中约定为最大值). 对于点 \(u\)\(v\)\(u\)\(v\)最小瓶颈路是两点间所有路径中瓶颈最小的. 最小瓶颈路可能有多个,我们通常只希望求出一条来. 下面我们证明:\(M\)\(G\) 的一个最小生成树,则 \(u\)\(v\)\(M\) 上的简单路径一定是 \(G\) 上的最小瓶颈路.

用反证法,假设 \(u\)\(v\)\(M\) 上的路径不是最小瓶颈路. 设最小瓶颈为 \(c\). 我们把路径上最大的那条边 \(w\)(根据假设,\(w>c\))删去,这将 \(M\) 分成两个连通块,一个包含 \(u\),另一个包含 \(v\). 考虑一条真正的最小瓶颈路,它从 \(u\) 走到 \(v\) 必定会跨过两个连通块,设跨过的这条边为 \(w'\),则有 \(w'\le c<w\). 现在把 \(w'\) 加回 \(M\)\(M\) 就变成了更小的生成树,这就导出了矛盾.

因此,给定图 \(G\),先求一棵最小生成树,再用树上倍增或树剖求路径最值,这就求出了最小瓶颈. 时间复杂度 \(O(m\log m+q\log n)\),其中 \(m\) 为边数,\(n\) 为点数,\(q\) 为询问次数.

Kruskal 重构树

参考 cqy 课件,在此表示感谢.

Kruskal 算法是对生成树性质的充分利用. 有时候我们需要记录算法过程中的某些信息,这需要Kruskal 重构树.

在算法进行过程中,Kruskal 重构树始终是一个森林(若 \(G\) 连通则最后会变成一棵树). 首先建立 \(n\) 个叶子结点,对应图 \(G\)\(n\) 个结点. 接下来进行 Kruskal 算法,按边权升序枚举 \(G\) 的边. 当一条边 \((u,v,w)\) 被跳过时不做操作,否则查出 \(u\)\(v\) 两点所在树的根 \(r_u\)\(r_v\)(此时一定有 \(r_u\ne r_v\)),新建权值为 \(w\) 的结点 \(p\),将 \(r_u\)\(r_v\) 设为 \(p\) 的儿子.

这样做的正确性显然,因为在任意时刻,\(u\)\(v\) 具有相同的树根当且仅当 \(u\)\(v\) 在 Kruskal 算法中是否已经连通. 事实上,这棵重构树本身类似于一个有边权的并查集(而且可查历史版本). 只需略微调整 Kruskal 算法中的并查集,每次不把 \(u\)\(v\) 直接合并而是把它们都与新根 \(p\) 合并(注意合并方向!),就能快速查出点所在树的根.

下面给出 Kruskal 重构树的一些性质.

  • 重构树是一棵有 \(n\) 个叶子的完满二叉树(非叶子节点恰有两个儿子).

注意:整棵重构树有 \(2n-1\) 个结点. 数组要开到 \(2\) 倍.

  • 非叶子结点的点权满足大根堆性质(父亲的权值大于等于左右儿子).
  • 最小生成树上 \(u\)\(v\) 的简单路径对应于重构树上叶子 \(u\) 到叶子 \(v\) 的简单路径.

这两条性质给出一种新的求最小瓶颈路的方法:在重构树上求两点的最近公共祖先,它的权值即为最小瓶颈.

例题

待续……

posted @ 2023-07-28 16:24  abcc!  阅读(87)  评论(0编辑  收藏  举报