最小生成树
最小生成树
我们定义无向连通图的 最小生成树(Minimum Spanning Tree,MST)为边权和最小的生成树。
注意:只有连通图才有生成树,而对于非连通图,只存在生成森林。
求解最小生成树常用的算法:
- Kruskal 算法
- Prim 算法
- Boruvka 算法
Kruskal 算法
该算法的基本思想是将所有的边,按照权重从小到大排序,然后依次选取每一条边,如果这条边的两个端点不属于同一集合,那么就将它们合并,否则就放弃选择次小的边,直到所有的点都属于同一个集合为止。
操作过程为:
- 将所有的边按照权重从小到大排序;
- 从图的边集数组中找到权值最小的边,将边的两个顶点连接起来;
- 继续寻找权值最小的边,将两个顶点之间连接起来,如果选择的边使得最小生成树出现了环路,则放弃该边,选择权值次小的边;
- 直到所有的顶点都被连接在一起并且没有环路,最小生成树就生成了。
其中,判断两个顶点是否属于同一个集合,可以直接使用前面的并查集算法。
对于 Union-Find算法 的代码模板,前面的文章已经介绍过了,这里不再赘述,参考前面的 Union-Find算法 即可。
应用
应用1:Leetcode.1135
题目
解题思路
所谓一个 带权图 的最小生成树,就是原图中边的权值最小的生成树 ,所谓最小是指边的权值之和小于或者等于其它生成树的边的权值之和。
先将所有的边按照权重从小到大排序,然后依次遍历排序后的边,如果边的两个顶点不属于同一个连通分量,就连接两个顶点,并累加权重,如果当前的边两个顶点属于同一个连通分量,则跳过当前的边。
最后,遍历完所有的边后,如果所有的顶点都属于同一个连通分量,那么,所有的顶点就可以构成一棵最小生成树。
代码实现
from typing import List class Solution: def minimumCost(self, n: int, connections: List[List[int]]) -> int: connections.sort(key=lambda x: x[2]) uf = UnionFind(n + 1) mst = 0 for connection in connections: if uf.connected(connection[0], connection[1]): continue mst += connection[2] uf.union(connection[0], connection[1]) if uf.get_count() != 2: return -1 return mst
应用2:Leetcode.1584
题目
解题思路
求最小生成树:
- 先将所有的点两两组合,计算权重,然后对所有的边按照权重排序;
- 遍历排序后的边,只要边的两个顶点属于不同的连通分量,就连接两个顶点,并累加权重。
代码实现
class Solution: def minCostConnectPoints(self, points: List[List[int]]) -> int: n = len(points) edges = list() for i in range(n - 1): for j in range(i + 1, n): cost = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]) edges.append((i, j, cost)) edges.sort(key = lambda x : x[2]) mst = 0 uf = UnionFind(n) for edge in edges: if uf.connected(edge[0], edge[1]): continue uf.union(edge[0], edge[1]) mst += edge[2] if uf.get_count() != 1: return -1 return mst
参考:
本文作者:LARRY1024
本文链接:https://www.cnblogs.com/larry1024/p/16997960.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步