【贪心算法】最小生成树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.rhkb.cn/news/321502.html

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

相关文章

聪明与诚实:社会信任的桥梁

在现代社会中&#xff0c;我们经常听到这样的评价&#xff1a;“某人真聪明。”然而&#xff0c;当我们深入思考时&#xff0c;会发现“聪明”这个词背后所承载的含义并不单一。聪明和狡诈往往被混淆&#xff0c;而诚实的价值却时常被忽视。在一个高度诚信的社会里&#xff0c;…

Arduino控制继电器,制作智能浇水系统

所需硬件材料 Arduino模块、继电器、直流电机、3-6v电池&#xff08;这个是必须的&#xff0c;电机不能直接接在arduino的5v引脚上&#xff0c;会引起电压不足&#xff09;、杜邦线 实现效果&#xff1a; 电机转动一秒停一秒 将硬件连接如下&#xff1a; 将电机连接到继电…

【电路笔记】-RC振荡器电路

RC振荡器电路 文章目录 RC振荡器电路1、概述2、RC 相移网络3、基本RC振荡器电路4、运算放大器RC振荡器5、运算放大器相位滞后RC振荡器电路6、RC振荡器示例11、概述 RC 振荡器使用放大器和 RC 反馈网络的组合,由于级之间的相移而产生输出振荡。 当单级晶体管放大器作为共发射…

使用API有效率地管理Dynadot域名,设置所有域名默认whois信息

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

asp.net成绩查询系统

说明文档 运行前附加数据库.mdf&#xff08;或sql生成数据库&#xff09; 主要技术&#xff1a; 基于asp.net架构和sql server数据库 功能模块&#xff1a; asp.net成绩查询系统 学生功能有查看成绩和修改账号密码等 后台管理员可以进行用户管理 管理员添加管理员查询注…

【unocss】自用

unocss中文官网1 不知道简写的可以在这里查 第一步 npm install -D unocss第二步 // vite.config.ts import UnoCSS from unocss/vite import { defineConfig } from viteexport default defineConfig({plugins: [UnoCSS()] })// main.ts import virtual:uno.css第三步 在…

【Gateway】网关集成Knife4j—swagger接口文档

文章目录 前言一、相关配置1.网关gateway配置①.网关增加配置 pom文件②.网关增加配置 SwaggerHandler③.网关增加配置 SwaggerResourceConfig④.网关增加配置 SwaggerConfig 2.网关过滤器 二、接口文档使用1.访问文档2.查看文档 总结 前言 在日常开发中是需要前后端联调的&am…

『ZJUBCA Collaboration』WTF Academy 赞助支持

非常荣幸宣布&#xff0c;浙江大学区块链协会收到WTF Academy的赞助与支持&#xff0c;未来将共同开展更多深度合作。 WTF Academy是开发者的Web3开源大学&#xff0c;旨在通过开源教育让100,000名开发者进入到Web3。截止目前&#xff0c;WTF开源教程在GitHub收获超15,000 ⭐&a…

【busybox记录】【shell指令】tr

目录 内容来源&#xff1a; 【GUN】【tr】指令介绍 【busybox】【tr】指令介绍 【linux】【tr】指令介绍 使用示例&#xff1a; 转换字符 - 默认 转换字符 - 不翻译指定字符数组 此指令目前接触少&#xff0c;用得少&#xff0c;把精力放到其他常用指令上 常用组合指令…

free5gc+ueransim操作

启动free5gc容器 cd ~/free5gc-compose docker-compose up -d 记录虚拟网卡地址&#xff0c;eth0 ifconfig 查看并记录amf网元的ip地址 sudo docker inspect amf "IPAddress"那一行&#xff0c;后面记录的即是amf的ip地址 记录上述两个ip地址&#xff0c;完成UER…

基于svm的手写数字识别程序介绍(matlab)

1、程序界面介绍 该程序GUI界面包括手写板、手写数字可视化&#xff08;原图&#xff09;、对图像进行灰度处理&#xff08;灰度图&#xff09;、图像二值化处理&#xff08;二值化&#xff09;、图像特征可视化&#xff08;HOG特征&#xff08;方向梯度直方图&#xff09;&…

Django高级表单处理与验证实战

合集 - 热门工具(70)1.ASCII编码的影响与作用&#xff1a;数字化时代的不可或缺之物02-252.短链接的背后故事&#xff1a;为互联网用户带来的便捷与安全02-263.二维码的背后故事&#xff1a;为用户带来的便捷与安全02-274.自由生成各种尺寸大小的占位图片&#xff1a;解决设计与…

使用 GPT-4-turbo+Streamlit+wiki+calculator构建Math Agents应用【Step by Step】

&#x1f496; Brief&#xff1a;大家好&#xff0c;我是Zeeland。Tags: 大模型创业、LangChain Top Contributor、算法工程师、Promptulate founder、Python开发者。&#x1f4dd; CSDN主页&#xff1a;Zeeland&#x1f525;&#x1f4e3; 个人说明书&#xff1a;Zeeland&…

蓝桥杯单片机之模块代码《AT24C02》

过往历程 历程1&#xff1a;秒表 历程2&#xff1a;按键显示时钟 历程3&#xff1a;列矩阵按键显示时钟 历程4&#xff1a;行矩阵按键显示时钟 历程5&#xff1a;新DS1302 历程6&#xff1a;小数点精确后两位ds18b20 历程7&#xff1a;35定时器测量频率 文章目录 过往历…

Android Studio查看xml文件的修改时间和记录

Android Studio查看xml文件的修改时间和记录 Android Studio里面如果是Java/Kotlin编写界面&#xff0c;可以点击函数开头上面的提交在直接&#xff0c;然后在编辑界面的左侧查看历史时间上的修改记录&#xff0c;但是xml文件里面没有直观的这样操作方式。 但xml里面可以通过快…

使用xshell工具连接ubuntu的root账户被拒绝的解决方法

问题描述&#xff1a; 我在使用xshell工具远程连接Ubuntu虚拟机的过程中&#xff0c;如果连接的是的普通用户则xshell工具可以正常连接&#xff0c;但是当我向连接ubuntu系统的root用户&#xff0c;即便是密码输入正确但还是不能连接成功。不能连接成功的截图如下&#xff1a; …

每日两题 / 138. 随机链表的复制 148. 排序链表(LeetCode热题100)

138. 随机链表的复制 - 力扣&#xff08;LeetCode&#xff09; 用哈希表记录原链表中的节点是否被复制过 遍历原链表并通过哈希表维护新链表 /* // Definition for a Node. class Node { public:int val;Node* next;Node* random;Node(int _val) {val _val;next NULL;rand…

python网络爬虫学习——编写一个网络爬虫

参考资料&#xff1a;用Python写网络爬虫&#xff08;第2版&#xff09; 1、编写一个函数 &#xff08;1&#xff09;用于下载网页&#xff0c;且当下载网页发生错误时能及时报错。 # 导入库 import urllib.request from urllib.error import URLError,HTTPError,ContentTooS…

什么是web3D?应用场景有哪些?如何实现web3D展示?

Web3D是一种将3D技术与网络技术完美结合的全新领域&#xff0c;它可以实现将数字化的3D模型直接在网络浏览器上运行&#xff0c;从而实现在线交互式的浏览和操作。 Web3D通过将多媒体技术、3D技术、信息网络技术、计算机技术等多种技术融合在一起&#xff0c;实现了它在网络上…

js宏任务微任务输出解析

第一种情况 setTimeout(function () {console.log(setTimeout 1) //11 宏任务new Promise(function (resolve) {console.log(promise 1) //12 同步函数resolve()}).then(function () {console.log(promise then) //13 微任务})})async function async1() {console.log(async1 s…