最小生成树相关拓展
求最小生成树的两个经典算法就是 Kruskal 与 Prim 算法,原理不过多阐述了,这里重点介绍有关最小生成树的一些拓展性质(最大生成树也同理):
相关性质
- 在最小生成树中,任意两点路径上的最大边权一定是原图中两点间所有路径里最小的。因此求普通无向图中任意两点间的最小瓶颈(即最大边权最小),就可以通过最小生成树 + 树上倍增维护静态路径边权最小来做。
Boruvka 算法
高效处理完全图的最小生成树(完全图内边数规模达到 \(O(n^{2})\),\(n = 10^{5}\),每条边一般由两个端点的权值加工定义得到)。
Kruskal 与 Prim 的最优复杂度都是 \(O(m\log m)\),而 Boruvka 的时间复杂度可以做到仅与 \(n\) 相关。
大致思路:初始时将所有点作为单独一个连通块。迭代若干次,每次要先找到每个连通块向外引出的所有边中边权最小的那条边(类似 Prim);然后按照 Kruskal 的思路,按边权升序遍历这些边,考虑将这些边加入到求解的最小生成树的边集合,并合并该边连接的两个连通块(若该边连接的两个连通块已经合并过,就不再加入答案,整个过程完全是 Kruskal 算法的流程)。直到最后只存在一个连通块,就得到了原图的最小生成树。
复杂度证明:可以证明迭代总次数不会超过 \(\log n\)。因为每轮合并后,连通块个数一定会至少减半(最好情况是一次全部合并成一个连通块;最差情况是每个连通块的最小边两两配对,数量规模大致缩减一半),而初始时有 \(n\) 个连通块,故得证。
总复杂度:\(O(n\log n * f)\),其中 \(f\) 代表求解每个连通块向外引出的最小边的复杂度,一般为 \(O(1)\) 或 \(O(\log)\)。
CF888G
Q:一个大小为 \(n \le 10^{5}\) 的完全图,每个点有权值 \(a_{i}\),其中 \((u, v)\) 的边权为 \(a_{u} \oplus a_{v}\),求最小生成树权值。
显然可以用 Boruvka 来求完全图的最小生成树,关键问题在于:如何求每个连通块向外引出的最小边权的那条边。假设现在有若干连通块,每个点都属于唯一的某个连通块中。那么对于某个连通块的答案,就是 该连通块内的某个点 与 不在该连通块内的某个点 形成的最小异或和,显然要考虑 01Trie。具体地:我们可以先将所有点加入到 Trie 内,然后对于某个连通块,先将里面的所有点从 Trie 中删除,然后再用该连通块中的所有点依次查询 Trie,得到最小异或和与相应的两个端点,再重新将这些点加入回 Trie。这样,我们就处理出来了每个连通块具有最小边权的引出边。每个连通块内的所有点相对于 Trie 做了 3 次操作,均摊下来总复杂度是 \(O(n\log A)\) 的。
次小生成树
分为 非严格次小生成树 与 严格次小生成树 两种,区分在于总边权是否可以等于原最小生成树。
非严格次小生成树:先求出某个最小生成树(称作原最小生成树),然后考虑用不在原最小生成树的某条边替换掉原最小生成树中的某条边。具体实现:枚举所有不在原最小生成树的边 \((u,v)\),并考虑将其加入到正在构造的生成树中。那么根据生成树的定义,从原最小生成树中去除掉的边,必须改变 \((u, v)\) 两点的连通性,也就是说,去除掉的边必须是 \((u, v)\) 在原最小生成树内的路径上的一条边。而由于需要求的是次小生成树,故我们必须去除该路径中边权最大的那条边(否则肯定不是次小生成树),而树上任意两点间的最大边权可以通过树上倍增查询得到。最终得到的所有总边权的最小值就是非严格次小生成树的权值。
严格次小生成树:此时需要规避掉所有权值等于原最小生成树,但不是原最小生成树本身的生成树。处理方式相比前者变化也很小:只需要额外维护树上路径的严格次大边权,在原最小生成树中删除的边也就是这条严格次大边。这样可以保证替换的那条边的边权严格大于被删除边,进而求出的生成树权值一定严格大于原最小生成树权值,即该生成树是严格次小生成树。
瓶颈生成树
定义:无向图的所有生成树中,最大边权最小的生成树。
最小生成树一定是瓶颈生成树,瓶颈生成树不一定是最小生成树。

浙公网安备 33010602011771号