📅  最后修改于: 2023-12-03 15:17:44.708000             🧑  作者: Mango
在图论中,最小生成树(Minimum Spanning Tree,MST)是指一个连接所有点的树中,边权值之和最小的树。在实际问题中,MST的应用非常广泛,例如:通信网络、电力磁网、航线规划等领域。目前,常用的MST算法有Prim算法和Kruskal算法,接下来将介绍这两种算法的区别。
Prim 算法是一种贪心算法,它采用了广度优先搜索策略。该算法维护两个集合:一个是已经放置在当前最小生成树中的节点集合,另一个则是还未被选择的节点集合。该算法开始时令已经放置在当前最小生成树集合中只有一个初始节点,因此仍然存在N - 1个节点未被选择。然后通过贪心策略在节点集合中选择一个离当前最小生成树最近的节点,把它加入最小生成树集合中。反复执行该过程,直到所有节点都被选入最小生成树集合,则得到最小生成树。
def Prim(G, s):
"""
:param G: 图的邻接矩阵表示
:param s: 起点
:return: 最小生成树的权值和
"""
n = len(G)
dist = [float("inf")] * n
visited = [False] * n
dist[s] = 0
for _ in range(n):
u = min(filter(lambda x: not visited[x], range(n)), key=dist.__getitem__)
visited[u] = True
for v in range(n):
if not visited[v] and G[u][v] < dist[v]:
dist[v] = G[u][v]
return sum(dist)
Kruskal算法是一种贪心算法,它采用了并查集来实现。该算法先把图中的边按照权值从小到大排序,然后从小到大扫描每一条边。对于每一条边,如果它所连接的两个节点不在同一个并查集中,就把它们合并到同一个并查集中,并把它加入最小生成树的集合中。重复执行该过程,直到所有节点都被选入最小生成树集合,则得到最小生成树。
def Kruskal(G):
"""
:param G: 图的邻接矩阵表示
:return: 最小生成树的权值和
"""
n = len(G)
edges = [(i, j, G[i][j]) for i in range(n) for j in range(i) if G[i][j] != float("inf")]
edges.sort(key=lambda x: x[2])
uf = UnionFind(n)
res = 0
for u, v, w in edges:
if uf.find(u) != uf.find(v):
uf.union(u, v)
res += w
return res
综上所述,两种算法有各自的适用场景,程序员需要选择合适的算法来解决问题。