力扣刷题之旅:高阶篇(四)—— 最小生成树算法

          力扣(LeetCode)是一个在线编程平台,主要用于帮助程序员提升算法和数据结构方面的能力。以下是一些力扣上的入门题目,以及它们的解题代码。   

力扣刷题之旅:高阶篇(四)—— 最小生成树算法_第1张图片


引言:

        在算法领域中,图论是一个重要且有趣的分支,而最小生成树问题则是图论中的一个经典问题。最小生成树算法用于在一个连通的加权无向图中找到一棵边权值之和最小的生成树。在实际应用中,最小生成树算法常用于网络设计、电路设计等领域。

一、最小生成树算法简介

  • 最小生成树算法主要有两种:Prim算法和Kruskal算法
  1. Prim算法
    1. 从一个顶点开始,每次选择一条连接已选顶点和未选顶点的最小权边,并将其加入生成树中,直到所有顶点都被选中。
  2. Kruskal算法
    1. 将所有边按照权值从小到大排序,然后依次选择边,如果这条边连接的两个顶点不在同一个连通分量中,则将其加入生成树中,直到生成树中包含所有顶点。

二、力扣上的最小生成树题目

题目:“最小生成树”

        给定一个带权无向图,其中每个节点表示一个城市,每条边表示两个城市之间的道路,边上的权重表示道路的长度。请找到该图的最小生成树,即一个包含所有节点的连通子图,使得子图中所有边的权值之和最小

输入格式

  • 第一行包含两个整数n和m,分别表示节点的数量和边的数量。
  • 接下来m行,每行包含三个整数u、v和w,表示节点u和节点v之间有一条权值为w的边。

输出格式

  • 输出一个整数,表示最小生成树的权值之和。

示例输入

4 5  
1 2 3  
1 3 1  
1 4 4  
2 3 2  
2 4 2

示例输出: 

7

解释

        上述输入表示一个包含4个节点和5条边的带权无向图。其中,节点1与节点2之间的边权值为3,节点1与节点3之间的边权值为1,节点1与节点4之间的边权值为4,节点2与节点3之间的边权值为2,节点2与节点4之间的边权值为2。最小生成树为包含边(1, 3)、(2, 3)和(2, 4)的子图,其权值之和为1 + 2 + 2 = 7。

三、解题代码

以下是使用Kruskal算法解决该问题的Python代码示例:
class UnionFind:  
    def __init__(self, n):  
        self.parent = list(range(n))  
        self.rank = [0] * n  
  
    def find(self, x):  
        if self.parent[x] != x:  
            self.parent[x] = self.find(self.parent[x])  
        return self.parent[x]  
  
    def union(self, x, y):  
        root_x = self.find(x)  
        root_y = self.find(y)  
        if root_x == root_y:  
            return False  
        if self.rank[root_x] < self.rank[root_y]:  
            root_x, root_y = root_y, root_x  
        self.parent[root_y] = root_x  
        if self.rank[root_x] == self.rank[root_y]:  
            self.rank[root_x] += 1  
        return True  
  
def kruskal(n, edges):  
    edges.sort(key=lambda x: x[2])  # 按照权值从小到大排序  
    uf = UnionFind(n)  
    mst_weight = 0  
    count = 0  
    for u, v, w in edges:  
        if uf.union(u - 1, v - 1):  # 注意节点编号从1开始,而数组索引从0开始  
            mst_weight += w  
            count += 1  
            if count == n - 1:  # 当生成树中包含所有节点时,结束循环  
                break  
    return mst_weight  
  
# 读取输入并计算最小生成树权值之和  
n, m = map(int, input().split())  
edges = []  
for _ in range(m):  
    u, v, w = map(int, input().split())  
    edges.append((u, v, w))  
print(kruskaln, edges))
示例输入与输出        if name == "main": 
# 示例输入
n, m = 4, 5
edges = [(1, 2, 3), (1, 3, 1), (1, 4, 4), (2, 3, 2), (2, 4, 2)]
# 计算最小生成树权值之和  
mst_weight = kruskal(n, edges)  
  
# 输出结果  
print(mst_weight)  # 输出应为 7


四、总结

         通过解决最小生成树问题,我们学习了两种常见的算法:Prim算法和Kruskal算法这两种算法都能够在加权无向图中找到权值之和最小的生成树。在实际应用中,最小生成树算法常用于构建网络中的最经济、最有效的连接方案。

你可能感兴趣的:(算法,leetcode,图论,python,数据结构,职场和发展)