最小生成树是一副连通加权无向图中一棵权值最小的生成树。一个连通图可能有多个生成树。当图中的边具有权值时,总会有一个生成树的边的权值之和小于或者等于其它生成树的边的权值之和 (Wikipedia)。
常见算法有 Kruskal 算法和 Prim 算法
Kruskal 算法
按照边的权重顺序(从小到大)将边加入生成树中,但是若加入该边会与生成树形成环则不加入该边。直到树中含有顶点数减一条边为止。这些边组成的就是该图的最小生成树。
实现过程中, 可利用小根堆来依次返回权重最小的边, 利用并查集来避免生成树形成回路.
Java
UnionFind 定义如下
1 | class UnionFind { |
Kruskal 实现
1 | public class KruskalMST { |
Python
UnionFindSet
定义见并查集
由于 Edge
对象不能够直接比较大小, 需重写 Edge
的比较函数, __lt__
对应 <
, __gt__
对应 >
, 只重写其中一个, 另一个会自动取反. 比较相等时结果相同.
1 | class Edge: |
Kruskal 实现
1 | from heapq import * |
Prim 算法
从任意一个节点开始, 将与其相连的几条边全部放入一个小根堆中, 每次弹出小根堆中权重最小的边, 获取该边的另一端节点放入集合中, 并将另一端节点的所有直接相连的边放入小根堆中, 迭代直到小根堆中的边全部取出为止.
Java
1 | public class PrimMST { |
1 | 1 3 2 4 5 |
Python
1 | def prim_mst(graph): |