📜  求解最小生成树(Kruskal 和 Prim)的问题(1)

📅  最后修改于: 2023-12-03 15:11:03.200000             🧑  作者: Mango

求解最小生成树(Kruskal 和 Prim)的问题

简介

在图论中,最小生成树是一种按照边的权值从小到大依次加入,最终连接所有顶点,且无环的生成树。求解最小生成树问题有两种经典算法:Kruskal 算法和 Prim 算法。

Kruskal 算法

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 算法

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 算法都是经典的求解最小生成树问题的算法,它们在实现和复杂度上稍有不同。使用时需要根据具体问题选择合适的算法。