📅  最后修改于: 2023-12-03 15:11:03.200000             🧑  作者: Mango
在图论中,最小生成树是一种按照边的权值从小到大依次加入,最终连接所有顶点,且无环的生成树。求解最小生成树问题有两种经典算法:Kruskal 算法和 Prim 算法。
Kruskal 算法先将边按照权值从小到大排序,然后依次选择权值最小的边,如果该边的两个端点不属于同一个连通块,就将它们合并。最终得到的就是整个图的最小生成树。
代码实现:
def kruskal(graph):
# 初始化每个点的祖先为自身
parent = {node: node for node in graph}
tree = []
edges = [(graph[node1][node2], node1, node2) for node1 in graph for node2 in graph[node1] if node1 < node2]
edges.sort() # 边按照权值排序
for weight, node1, node2 in edges:
while node1 != parent[node1]:
node1 = parent[node1]
while node2 != parent[node2]:
node2 = parent[node2]
if node1 != node2: # 该边的两端不属于同一个连通块
tree.append((node1, node2, weight))
parent[node1] = node2
return tree
Prim 算法从任意一个点开始,然后选出与该点相邻的权值最小的边,将其加入生成树中。然后,将该边的边另外一个端点作为起点,重复上述步骤,直至所有节点都被遍历过。
代码实现:
import heapq
def prim(graph):
visited = set()
start = list(graph.keys())[0] # 从第一个节点开始遍历
visited.add(start)
edges = [(weight, start, node) for node, weight in graph[start].items()]
heapq.heapify(edges) # 将边维护成一个小根堆
tree = []
while edges:
weight, node1, node2 = heapq.heappop(edges)
if node2 not in visited:
visited.add(node2)
tree.append((node1, node2, weight))
for next_node, next_weight in graph[node2].items():
if next_node not in visited:
heapq.heappush(edges, (next_weight, node2, next_node))
return tree
Kruskal 算法和 Prim 算法都是经典的求解最小生成树问题的算法,它们在实现和复杂度上稍有不同。使用时需要根据具体问题选择合适的算法。