【贪心算法】最小生成树Kruskal算法Python实现

文章目录

    • @[toc]
      • 问题描述
      • 最小生成树的性质
        • 证明
      • `Kruskal`算法
      • `Python`实现
      • 时间复杂性

问题描述

  • G = ( V , E ) G = (V , E) G=(V,E)是无向连通带权图, E E E中每条边 ( v , w ) (v , w) (v,w)的权为 c [ v ] [ w ] c[v][w] c[v][w]
  • 如果 G G G的一个子图 G ′ G^{'} G是一棵包含 G G G的所有顶点的树,则称 G ′ G^{'} G G G G的生成树
  • 生成树上各边权的总和称为该生成树的耗费,在 G G G的所有生成树中,耗费最小的生成树称为 G G G的最小生成树

最小生成树的性质

  • G = ( V , E ) G = (V , E) G=(V,E)是连通带权图, U U U V V V的真子集,如果 ( u , v ) ∈ E (u , v) \in E (u,v)E,且 u ∈ U u \in U uU v ∈ V − U v \in V - U vVU,且在所有这样的边中, ( u , v ) (u , v) (u,v)的权 c [ u ] [ v ] c[u][v] c[u][v]最小,那么一定存在 G G G的一棵最小生成树,它以 ( u , v ) (u , v) (u,v)为其中一条边
  • 这个性质有时也称为 M S T MST MST性质
证明
  • 假设 G G G的任何一棵最小生成树都不包含边 ( u , v ) (u , v) (u,v),将边 ( u , v ) (u , v) (u,v)添加到 G G G的一棵最小生成树 T T T上,将产生含有边 ( u , v ) (u , v) (u,v)的圈,并且在这个圈上有一条不同于 ( u , v ) (u , v) (u,v)的边 ( u ′ , v ′ ) (u^{'} , v^{'}) (u,v),使得 u ′ ∈ U u^{'} \in U uU v ′ ∈ V − U v^{'} \in V - U vVU,如下图所示

1

  • 将边 ( u ′ , v ′ ) (u^{'} , v^{'}) (u,v)删去,得到 G G G的另一棵生成树 T ′ T^{'} T,由于 c [ u ] [ v ] ≤ c [ u ′ ] [ v ′ ] c[u][v] \leq c[u^{'}][v^{'}] c[u][v]c[u][v],所以 T ′ T^{'} T的耗费 ≤ T \leq T T的耗费,于是 T ′ T^{'} T是一棵含有边 ( u , v ) (u , v) (u,v)的最小生成树,与假设矛盾

Kruskal算法

  • 给定无向连通带权图 G = ( V , E ) G = (V , E) G=(V,E) V = { 1 , 2 , ⋯ , n } V = \set{1 , 2 , \cdots , n} V={1,2,,n}
  • 首先将 G G G n n n个顶点看成 n n n个孤立的连通分支,将所有的边按权从小到大排序,然后从第一条边开始,依边权递增的顺序查看每条边,并按下述方法连接两个不同的连通分支
  • 当查看到第 k k k条边 ( v , w ) (v , w) (v,w)时,如果端点 v v v w w w分别是当前两个不同的连通分支 T 1 T_{1} T1 T 2 T_{2} T2中的顶点时,就用边 ( v , w ) (v , w) (v,w) T 1 T_{1} T1 T 2 T_{2} T2连接成一个连通分支,然后继续查看第 k + 1 k + 1 k+1条边;如果端点 v v v w w w在当前的同一个连通分支中,就直接再查看第 k + 1 k + 1 k+1条边
  • 这个过程一直进行到只剩下一个连通分支时为止,此时这个连通分支就是 G G G的一棵最小生成树

Python实现

class Graph:def __init__(self, vertices):self.V = vertices  # 图中顶点的数量self.graph = []  # 存储图的边的列表def addEdge(self, u, v, w):self.graph.append([u, v, w])  # 添加边到图的边列表def find(self, parent, i):if parent[i] == i:  # 如果顶点 i 的根节点是自身, 则返回 ireturn ireturn self.find(parent, parent[i])  # 递归查找 i 的根节点def union(self, parent, rank, x, y):root_x = self.find(parent, x)  # 查找顶点 x 的根节点root_y = self.find(parent, y)  # 查找顶点 y 的根节点if rank[root_x] < rank[root_y]:  # 如果 x 的根节点的秩小于 y 的根节点的秩parent[root_x] = root_y  # 将 x 的根节点连接到 y 的根节点elif rank[root_x] > rank[root_y]:  # 如果 x 的根节点的秩大于 y 的根节点的秩parent[root_y] = root_x  # 将 y 的根节点连接到 x 的根节点else:  # 如果 x 和 y 的根节点的秩相同parent[root_y] = root_x  # 将 y 的根节点连接到 x 的根节点rank[root_x] += 1  # 增加 x 的根节点的秩def kruskalMST(self):result = []  # 存储最小生成树的边的列表i = 0  # 当前处理的边的索引e = 0  # 已经加入最小生成树的边的数量self.graph = sorted(self.graph, key=lambda x: x[2])  # 按照边的权重对图的边进行排序parent = []  # 存储顶点的父节点rank = []  # 存储顶点的秩for node in range(self.V):parent.append(node)  # 每个顶点的初始父节点是自身rank.append(0)  # 每个顶点的初始秩是 0while e < self.V - 1:  # 当最小生成树的边的数量小于 V - 1 时, 继续循环u, v, w = self.graph[i]  # 获取当前处理的边的源顶点、目标顶点和权重i += 1  # 增加边的索引x = self.find(parent, u)  # 查找 u 的根节点y = self.find(parent, v)  # 查找 v 的根节点if x != y:  # 如果 u 和 v 不在同一个连通分量中(不会形成环路)e += 1  # 增加已加入最小生成树的边的数量result.append([u, v, w])  # 将该边加入最小生成树的结果中self.union(parent, rank, x, y)  # 合并 u 和 v 所在的连通分量print('边\t\t权')for u, v, weight in result:print(f'{u} - {v}\t{weight}')  # 打印最小生成树的边和权重g = Graph(5)g.addEdge(0, 1, 2)
g.addEdge(0, 3, 6)
g.addEdge(1, 3, 8)
g.addEdge(1, 2, 3)
g.addEdge(1, 4, 5)
g.addEdge(2, 4, 7)
g.addEdge(3, 4, 9)g.kruskalMST()
边		权
0 - 1	2
1 - 2	3
1 - 4	5
0 - 3	6

时间复杂性

  • 当图的边数为 e e e时,Kruskal算法所需的时间是 O ( e log ⁡ e ) O(e \log{e}) O(eloge)
  • e = Ω ( n 2 ) e = \Omega(n^{2}) e=Ω(n2)时,Kruskal算法比Prim算法差,当 e = o ( n 2 ) e = o(n^{2}) e=o(n2)时,Kruskal算法比Prim算法好得多

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/10453.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

acer笔记本怎样进行系统还原?教你两招!

acer笔记本怎样进行系统还原&#xff1f;教你两招&#xff01; 作为笔记本用户&#xff0c;你在日常使用中可能会遇到各种各样的电脑问题。一般来说&#xff0c;对于一些小问题&#xff0c;我们可以通过一些简单的操作来解决&#xff0c;比如重新启动电脑或者长按电源键强制关机…

提高静态住宅代理稳定性妙招

在数字化时代的浪潮中&#xff0c;静态住宅代理因其独特的优势&#xff0c;如固定的IP地址、更高的隐私保护性等&#xff0c;逐渐成为网络爬虫、数据分析等领域不可或缺的工具。然而&#xff0c;静态住宅代理的稳定性问题一直是用户关注的焦点。本文将为您揭示提高静态住宅代理…

docker compose kafka集群部署

kafka集群部署 目录 部署zookeeper准备工作2、部署kafka准备工作3、编辑docker-compose.yml文件4、启动服务5、测试kafka6、web监控管理 部署zookeeper准备工作 mkdir data/zookeeper-{1,2,3}/{data,datalog,logs,conf} -p cat >data/zookeeper-1/conf/zoo.cfg<<EOF…

JS代码随想录(一):数组

代码随想录 一、数组理论基础 二、LeetCode 704. 二分查找 三、LeetCode 27. 移除元素 四、LeetCode 977.有序数组的平方 五、LeetCode 209.长度最小的子数组 六、LeetCode 59.螺旋矩阵II 七、数组总结 一、数组理论基础 数组是存放在连续内存空间上的相同类型数据的集合。 数组…

boost asio同步编程(附源码api)

首先注明&#xff0c;这里我写的都是关于tcp的通信。 通信大致流程 创建端点 创建tcp端点的api是boost::asio::ip::tcp::endpoint; 当然创建udp端点的api则是boost::asio::ip::udp::endpoint; 是一个表示 TCP/UDP 端点的类&#xff0c;在 Boost.Asio 库中用于网络编程。它通…

鸿蒙ArkUI:【编程范式:命令式->声明式】

命令式 简单讲就是需要开发用代码一步一步进行布局&#xff0c;这个过程需要开发全程参与。 开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。 Objective-C ObjectiveC 复制代码 UIView *cardView …

day3_prefixSum

一、前缀和技巧 重点 前缀和技巧适用于快速、频繁地计算一个索引区间内的元素之和 个人理解&#xff1b;预计算&#xff0c;空间换时间 1.(一维数组的前缀和)303区域和检索-数组不可变 获取闭区间值 [left,right] -> preSum[right 1] - preSum[left],其中preSum[right…

Linux下VMamba 环境复现+环境测试

# 1. 创建自己的虚拟环境 conda create -n VMamba python3.10.13 conda activate VMamba # 2. cuda-11.8 conda install cudatoolkit11.8 -c nvidia # 3. torch torchvision torchaudio 与 官网命令一致 pip install torch2.1.1 torchvision0.16.1 torchaudio2.1.1 --index-url…

苹果电脑怎么清内存?2024有哪些好用的工具?

在使用苹果电脑的过程中&#xff0c;我们可能会遇到系统运行缓慢、程序响应迟缓或频繁出现应用程序崩溃的情况&#xff0c;这些问题很可能是由于内存占用过高所导致。内存&#xff0c;或称为RAM&#xff08;RandomAccessMemory&#xff09;&#xff0c;是计算机的临时存储区&am…

超级好看的html网站维护源码

源码介绍 好看的html网站维护源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c; 源码截图 源码下载 好看的html网站维护源码

py黑帽子学习笔记_网络编程工具

tcp客户端 socket.AF_INET表示使用标准IPV4地址和主机名 SOCK_STREAM表示这是一个TCP客户端 udp客户端 udp无需连接&#xff0c;因此不需要client.connect这种代码 socket.SOCK_DGRAM是udp的 tcp服务端 server.listen(5)表示设置最大连接数为5 发现kill server后端口仍占用…

【服务治理中间件】consul介绍和基本原理

目录 一、CAP定理 二、服务注册中心产品比较 三、Consul概述 3.1 什么是Consul 3.2 Consul架构 3.3 Consul的使用场景 3.4 Consul健康检查 四、部署consul集群 4.1 服务器部署规划 4.2 下载解压 4.3 启动consul 五、服务注册到consul 一、CAP定理 CAP定理&#xff…

i春秋-Backdoor

题目 考点 git源码泄露 Linux文件恢复 代码审计 http 解题 参考wp https://blog.csdn.net/cbhjerry/article/details/105791056https://www.pianshen.com/article/19461342501/扫描 题目给出提示&#xff1a;敏感文件泄漏 于是使用dirsearch扫一下 python dirsearch.py -…

ICode国际青少年编程竞赛- Python-4级训练场-while语句综合

ICode国际青少年编程竞赛- Python-4级训练场-while语句综合 1、 for i in range(4):while not Flyer[i].disappear():wait()Spaceship.step(6)Spaceship.turnLeft()2、 Dev.turnLeft() for i in range(4):Spaceship.step(2)while Flyer[i].disappear():wait()Dev.step(4)Dev.…

Failed to parse source map (@toast-ui/editor/dist/purify.js.map)

使用 toast-ui-editor 时出现报错&#xff1a;Failed to parse source map (toast-ui/editor/dist/purify.js.map) 解决方法很简单&#xff1a; "start": "set "GENERATE_SOURCEMAPfalse" && react-scripts start ",在启动脚本时添加执…

程序员代码面试指南题目解析(一)

题目一&#xff1a;如何仅用递归函数和栈操作逆序一个栈 题目要求&#xff1a; 一个栈依次压入 1、2、3、4、5&#xff0c;那么从栈顶到栈底分别为5、4、3、2、1。将这个栈 转置后&#xff0c;从栈顶到栈底为 1、2、3、4、5&#xff0c;也就是实现栈中元素的逆序&#xff0c;但…

【吴恩达机器学习-week2】多个变量的线性回归问题

文章目录 1.1 目标2 问题陈述2.1 包含我们示例的矩阵 X2.2 参数向量 w \mathbf{w} w 和 b b b 3 使用多个变量进行模型预测3.1 逐元素单独预测3.2 单一预测&#xff0c;向量 4 使用多个变量计算成本5 使用多个变量的梯度下降5.1 使用多个变量计算梯度 多个变量的梯度下降小结…

搜歌网搜索各种类型音乐,统统歌曲转换格式mp3,轻松实现音乐自由!

在互联网的广阔天地中&#xff0c;音乐爱好者们总能找到满足自己需求的平台。其中&#xff0c;支持全网搜歌的网站无疑是一个值得推荐的音乐探索乐园。无论是寻找经典老歌&#xff0c;还是发掘新兴音乐&#xff0c;搜他们都能为音乐爱好者提供一站式的服务。 一般支持全网搜索…

值得收藏!!《软考信息处理技术员》必背100母题,轻松45+

距离软考考试的时间越来越近了&#xff0c;趁着这两周赶紧准备起来 今天给大家整理了——软考信息处理技术员100道经典母题&#xff0c;年年从里面抽&#xff0c;有PDF&#xff0c;可打印&#xff0c;每天刷几道。 第一章 电脑的基本操作 1、&#xff08; &#xff09;不是国产…

Linux线程(二)线程互斥

目录 一、为什么需要线程互斥 二、线程互斥的必要性 三、票务问题举例&#xff08;多个线程并发的操作共享变量引发问题&#xff09; 四、互斥锁的用法 1.互斥锁的原理 2、互斥锁的使用 1、初始化互斥锁 2、加锁和解锁 3、销毁互斥锁&#xff08;动态分配时需要&#…