【贪心】最小生成树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的一棵最小生成树

时间复杂性

  • 当图的边数为 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算法好得多

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

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

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

相关文章

asp.net(c#) 将dbf转换为xls或wps,并将数据的列名改成中文;并判断本机是否安装office2003,2007和wps2007,2010...

using Microsoft.Office.Interop.Excel;//转换为excel时&#xff0c;需要引用此命名空间 using ET;//转换为wps时&#xff0c;需要引用此命名空间using KSO;//转换为wps时&#xff0c;需要引用此命名空间当转换为excel时&#xff0c;需要引入Microsoft.Office.Interop.Excel.dl…

Java GregorianCalendar getActualMaximum()方法与示例

GregorianCalendar类getActualMaximum()方法 (GregorianCalendar Class getActualMaximum() method) getActualMaximum() method is available in java.util package. getActualMaximum()方法在java.util包中可用。 getActualMaximum() method is used to get the actual maxim…

一点一滴学习Linux--Mysql篇

1.查看是否安装了Mysql [rootlocalhost zhoulinghong]# rpm -qa |grep MySQL MySQL-server-community-5.1.22-0.rhel4 已经安装了。 2.安装mysql&#xff08;rpm&#xff09; [rootlocalhost zhoulinghong]# rpm -ivh MySQL-server-community-5.1.22-0.rhel4.i386.rpm …

HTML5 学习笔记

HTML5 学习笔记 前言 该学习笔记的相关学习视频&#xff1a;【狂神说Java】HTML5完整教学通俗易懂 目前笔记只有简单的例子和框架&#xff0c;将来在实践中会进一步学习和补充内容 目录HTML5 学习笔记前言网页基本信息网页基本标签标题标签段落标签换行标签水平线标签字体样式…

面向对象(方法的形式参数)

1&#xff0c;局部变量与成员变量的区别 1&#xff0c;在类中的位置不同 成员变量&#xff1a;在类中方法外 局部变量&#xff1a;在方法定义中或者方法声明上2&#xff0c;在内存中的位置不同 成员变量&#xff1a;在堆内存&#xff08;成员变量属于对象&#xff0c;对象进…

保护机制

0x01 概述 操作系统提供了许多安全机制来尝试降低或阻止缓冲区溢出攻击带来的安全风险&#xff0c;包括DEP、ASLR等。在编写漏洞利用代码的时候&#xff0c;需要特别注意目标进程是否开启了DEP&#xff08;Linux下对应NX&#xff09;、ASLR&#xff08;Linux下对应PIE&#xf…

机器学习降维算法一:PCA(主成分分析算法)

引言&#xff1a; 机器学习领域中所谓的降维就是指采用某种映射方法&#xff0c;将原高维空间中的数据点映射到低维度的空间中。降维的本质是学习一个映射函数 f : x->y&#xff0c;其中x是原始数据点的表达&#xff0c;目前最多使用向量表达形式。 y是数据点映射后的低维向…

VS 2005模板丢失找回的办法

安装其他插件的时候&#xff0c;常常模板丢失&#xff0c;比较郁闷&#xff0c;以前就用土办法&#xff0c;重装VS来解决这个问题&#xff0c;这次终于弄清楚怎么回事了&#xff0c;可以采取下面两个步骤解决1。复制ProjectTemplates和ItemTemplates&#xff0c;保证VS能找到相…

dbms数据库管理系统_基本数据库管理系统(DBMS)能力问题和解答

dbms数据库管理系统This section contains the aptitude questions and answers on basic concepts of DBMS. You will find aptitude questions on DDL, DCL, DML, DQL, TCL statements and other related topics. 本节包含有关DBMS基本概念的能力问题和解答。 您将找到有关DD…

面向对象(封装对象private关键字)

1.面向对象(封装的概述) A:封装概述 是指隐藏对象的属性和实现细节&#xff0c;仅对外提供公共访问方式。B:封装好处 隐藏实现细节&#xff0c;提供公共的访问方式提高了代码的复用性提高安全性。C:封装原则 将不需要对外提供的内容都隐藏起来。把属性隐藏&#xff0c;提供公…

Codeforces Global Round 13 C

C. Pekora and Trampoline 题意&#xff1a;对于数组a&#xff0c;每次出发开始可以选择任意元素作为起始点&#xff0c;然后在数组上移动&#xff0c;落点为i a[i]&#xff0c;直至超出数组范围&#xff0c;每次经过的点的值减一&#xff08;先移动再减/直至减到1为止&#…

一个简单的pwn例子---read函数

内容&#xff1a; #include<stdio.h> void exploit() {system("/bin/sh"); } void func() {char str[0x20];read(0, str, 0x50); } int main() {func();return 0; }我们要做的是利用溢出执行exploit函数 分析&#xff1a; 先执行func函数&#xff0c;func函数…

重载运算符 减号_在C / C ++中使用减号(-)运算符将两个数字相加

重载运算符 减号Given two numbers, and the task is to find their addition using the minus (-) operator. 给定两个数字&#xff0c;任务是使用减(-)运算符查找它们的加法 。 As we have discusses in C/C arithmetic operators that plus () operator adds the numbers a…

【操作系统】互斥:软件解决方法

互斥&#xff1a;软件解决方法 算法一 算法思路 预留一个全局内存区域&#xff0c;并标记为turn。进程&#xff08;P0或P1&#xff09;想进入它的临界区执行时&#xff0c;要先检查turn的内容。若turn的值等于进程号&#xff0c;则该进程可以进入它的临界区&#xff1b;否则…

Oracle为即将发布的11g开发平台进行预演

Oracle为即将发布的11g开发平台进行预演 Oracle JDeveloper是一个免费的整合开发环境&#xff0c;它为模块化、开发、调试、优化、部署Java应用程序和Web服务提供了端到端&#xff08;end-to-end&#xff09;的支持。1&#xff09;完全支持J2EE5.0&#xff0c;带有EJB3.0&#…

面向对象 多态

面向对象 多态的概述及其代码的体现 A&#xff1a;多态(polymorphic)概述 事物存在的多种形态B&#xff1a;多态前提 要有继承关系要有方法重写要有弗雷引用指向子类对象。C&#xff1a;案例演示 代码体现多态 public class Dome1 { public static void main(String[] args…

Web开发入门

想要学习Web开发&#xff0c;我的建议是参照Web应用的发展历史学习。最早的时候&#xff0c;Web应用就是静态的Html页面&#xff0c;不能和用户交互&#xff0c;这是因为它最早是各高校用来分享论文的载体。后来&#xff0c;随着Internet的流行&#xff0c;Web应用的用户不再单…

算法和程序的区别

算法 计算机算法是以一步接一步的方式来详细描述计算机如何将输入转化为所要求的输出的过程&#xff0c;或者说&#xff0c;算法是对计算机上执行的计算过程的具体描述。 算法首先必须是正确的&#xff0c;即对于任意的一组输入&#xff0c;包括合理的输入与不合理的输入&…

【图论】(二分图)J. Burnished Security Updates - CodeForces

J. Burnished Security Updates 题意&#xff1a;对于所给的图&#xff08;不一定连通&#xff09;&#xff0c;选择一些点作为一个集合&#xff0c;满足每条边有且仅有一个端点为该集合的点&#xff0c;要求计算该集合大小的最小可能&#xff0c;若无法找到一个集合满足条件则…

万网与阿里巴巴业务关系图解

阿里巴巴在港上市公司今天发布公告称&#xff0c;计划分拆旗下中国万网赴美上市。那么万网与阿里巴巴其它业务是怎样个关系&#xff1f;且看我们分析。 随着传统企业大面积地转向互联网经营&#xff0c;用电子商务来服务客户&#xff0c;它们面临的第一个问题就是建站。针对这一…