最小生成树学习记录
前置知识和定义
在开始学习最小生成树之前,先了解一些前置知识。
子图
对于一张图 ,如果存在一张图 满足 且 ,则称 是 的一个子图。记作 。
生成子图
如果存在 满足 ,则称 是 的一个生成子图。
生成子图又称为支撑子图。
生成树
生成树:一个无向连通图的生成子图,且同时要求是树。也即在图的边集选择了 条边,将图中的所有顶点连接起来。
最小生成树
我们定义,一个无向连通图的 最小生成树,是指这个图中边权和最小的生成树。
Kruskal 算法
Kruskal 算法是一种常见简单的用于求最小生成树的算法。此算法的基本思想就是贪心的从小到大加入边。
算法流程
- 对图中的所有边按边权从小到大排序。
- 从小到大枚举每一条边 ,如果 和 不在同一连通块中,就加入这条边,并将 和 所在的连通块合并。
- 重复步骤 2 直到加入了 条边。
显然,我们需要使用并查集来维护每个点所在的连通块。那么,此算法的时间复杂度就为 ,其中 是边数。
证明
归纳法证明
我们使用数学归纳法证明 Kruskal 算法的正确性。
基础:算法开始前,显然成立。
归纳:假设算法在加入了 条边后,生成了一个最小生成树 。我们需要证明,加入第 条边 后,生成的最小生成树 也成立。
我们可以分两种情况讨论:
- 如果 不在 中,那么 就是 加上 这条边。显然, 是一个最小生成树。
- 如果 在 中,那么 就是 去掉 这条边,加上 这条边的最小生成树。根据归纳假设, 是一个最小生成树,所以 也是一个最小生成树。
反证法
我们使用反证法证明 Kruskal 算法的正确性。
假设 Kruskal 算法得到的生成树 不是最小生成树,那么必然存在某个最小生成树 ,使得 ,其中 表示生成树的边权和。
设 是 Kruskal 算法选择的第一个不在 中的边(按边权从小到大排序后的第 条边)。由于 Kruskal 算法会选择这条边,说明在加入 之前, 和 不在同一个连通块中。
现在考虑 ,这个图必然包含一个环(因为 是生成树,加入任何边都会形成环)。这个环中至少包含一条边 满足 (因为 是连接这两个连通块的最小权边)。
我们可以构造一个新的生成树 。显然:
- 仍然是一个生成树(因为去除了环中的一条边)
- (因为 )
但是这与 是最小生成树的假设矛盾,因为我们找到了一个权值不大于 的生成树 ,且 包含了 。
通过重复这个过程,我们可以证明 Kruskal 算法得到的生成树 必须是最小生成树,从而证明了算法的正确性。