Kruskal算法详解:理解最小生成树问题及其解决方案
一、最小生成树问题
最小生成树问题是指在一个带权连通图中,找到一棵包含所有顶点且边权之和最小的生成树。所谓生成树,是指一个无向图中的生成树是该无向图的子图,它是一棵树,它包含了原图中的所有顶点且边数最小。
二、Kruskal算法的思想及流程
Kruskal算法的思路类似于贪心算法:
- 建立边集合E,将所有边按照边权从小到大排序;
- 初始化并查集,将每个节点都初始化成不同的集合;
- 依次将权值最小的边加入生成树中,若加入后不会形成环,则将该边加入生成树,否则舍弃该边;
- 重复步骤3,直至生成树中含有所有节点为止。
图解:以以下带权图为例,我们来演示Kruskal算法的流程。
-
将所有边按照边权从小到大排序,得到的边集合为:[(A,B,3), (B,D,3), (B,C,6), (A,E,7), (C,D,8), (D,F,9), (E,F,10), (C,E,12)]
-
初始化并查集,将每个节点都初始化成不同的集合。
A | B | C | D | E | F |
---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 |
- 依次将权值最小的边加入生成树中,若加入后不会形成环,则将该边加入生成树,否则舍弃该边。
第一条边为(A,B,3),将其加入生成树中。此时,A和B在同一个集合中,更新并查集。
A,B | C | D | E | F |
---|---|---|---|---|
1 | 2 | 3 | 4 | 5 |
生成树:
第二条边为(B,D,3),将其加入生成树中。此时,B和D在同一个集合中,更新并查集。
A,B,D | C | E | F |
---|---|---|---|
1 | 2 | 4 | 5 |
生成树:
第三条边为(B,C,6),将其加入生成树中。此时,B和C不在同一个集合中,加入该边不会形成环,更新并查集。
A,B,C,D | E | F |
---|---|---|
1 | 4 | 5 |
生成树:
第四条边为(A,E,7),将其加入生成树中。此时,A和E不在同一个集合中,加入该边不会形成环,更新并查集。
A,B,C,D,E | F |
---|---|
1 | 5 |
生成树:
第五条边为(C,D,8),将其加入生成树中。此时,C和D不在同一个集合中,加入该边不会形成环,更新并查集。
A,B,C,D,E | F |
---|---|
1 | 5 |
生成树:
第六条边为(D,F,9),将其加入生成树中。此时,D和F不在同一个集合中,加入该边不会形成环,更新并查集。
A,B,C,D,E,F |
---|
1 |
生成树:
第七条边为(E,F,10),将其加入生成树中。此时,E和F不在同一个集合中,加入该边不会形成环,更新并查集。
A,B,C,D,E,F |
---|
1 |
生成树:
第八条边为(C,E,12),将其加入生成树中。此时,C和E不在同一个集合中,加入该边不会形成环,更新并查集。
A,B,C,D,E,F |
---|
1 |
生成树:
至此,生成树中含有所有节点,算法结束。
三、Kruskal算法的实现
实际上,Kruskal算法的核心在于并查集的实现,具体实现可以参考以下Python代码:
相关文章