U4_2:图论之MST/Prim/Kruskal

news2024/11/23 13:25:47

文章目录

  • 一、最小生成树-MST
    • 生成MST策略
      • 一些定义
    • 思路
    • 彩蛋
  • 二、普里姆算法(Prim算法)
    • 思路
    • 算法流程
      • 数据存储
        • 分析
    • 伪代码
    • 时间复杂度分析
  • 三、克鲁斯卡尔算法(Kruskal算法)
    • 分析
    • 算法流程
      • 并查集-Find-set
    • 伪代码
    • 时间复杂度分析

一、最小生成树-MST

无向图,无环,所有点连通,边权重和最小
(没有权重标注就默认为1)
在这里插入图片描述

生成MST策略

  1. 从一个空图开始。
  2. 尝试一次添加一条边,始终确保所构建的保持无循环。
  3. 如果在添加了每条边之后,我们确定生成的图是某个最小生成树的子集,我们就完成了。

一些定义

集合 A A A是最小生成树 T T T的子集,当 A   U ( u , v ) A\space U(u,v) A U(u,v)也是 M S T MST MST子集时, ( u , v ) (u,v) (uv)是安全的。
切割 c u t cut cut ( S , V − S ) (S,V-S) (S,VS)
a a a c u t cut cut r e s p e c t s respects respects a a a s e t set set A A A o f of of e d g e s edges edges i f if if n o no no e d g e s edges edges i n in in A A A c r o s s e s crosses crosses t h e the the c u t cut cut.
An edge is a light edge crossing a cut if its weight is the minimumof any edge crossing the cut
在这里插入图片描述

思路

(S, V - S) be any cut of G that respects A
(u, v) be a light edge crossing the cut (S, V - S)Then, edge (u, v) is safe for A.
则 lt means that we can find a safe edge by

  1. first finding a cut that respects A
  2. then finding the light edge crossingthat cut
    That light edge is a safe edge

彩蛋

本质上下面所要讲的Prim算法和Kruskal算法都是依据这个总思路来的,先分隔cut,然后根据cut找light edge,最后不断生成MST

二、普里姆算法(Prim算法)

思路

  1. 首先选择任意顶点r作为树的根。
  2. 当树不包含图中的所有顶点时:找到离开树的最短边并将其添加到树中。
    这个思路可以想到,每次的cut就是选入作为顶点的集合 S S S和未选入的顶点 G − S G-S GS

算法流程

数据存储

区分cut:最初始是空集,所有顶点被标记为白色,选入的顶点标记为黑色
利用优先队列存储
利用优先队列(小顶堆)去寻找 t h e the the l i g h e s t lighest lighest e d g e edge edge(相应函数如下)
3. I n s e r t ( u , k e y ) Insert(u, key) Insert(u,key):用键值key在Q中插入u。
4. u = E x t r a c t − m i n ( ) u = Extract- min() u=Extractmin():提取键值最小的项。
5. D e c r e a s e − K e y ( u , n e w − k e y ) Decrease-Key(u, new-key) DecreaseKey(u,newkey):将u的键值减小为new-key
利用 p r e d [ A ] pred[A] pred[A]去存储每个顶点的存储顺序

分析

t h e the the l i g h e s t lighest lighest e d g e edge edge本质上是在黑白分界点的这些边中寻找,因此每次更新都需要维护这些点( k e y key key)。
初始的时候设为 i n i f i n i t y inifinity inifinity,每次加入新顶点时就找到它的所有边判断是否比现在的key是否更小了,如果更小了就可以更新并且换前驱
在这里插入图片描述

伪代码

for u ∈ V do
	color[u] ← white,key[u] ← +∞
end
key[u] ← 0,pred[r] ← null;	//最开始的顶点
Q ← new PriQueue(V)   
while Q is  noempty do
	u ← Q.Extract-Min(); //the lighest edge   
	for v ∈ adj[u] do
		if(color[u] ← white && w[u,v] < key[u]) then
			key[u] ← w[u,v]
			Q.decrease-Key(v,key[u]) 
			pred[v] ← u
		end
	end
	color[u] ← black
end

时间复杂度分析

创建优先队列 O ( V l o g V ) O(VlogV) O(VlogV),每次循环 E x t r a c t − M i n Extract-Min ExtractMin l o g ( V ) log(V) log(V),总共V个顶点,总时间复杂度为 O ( V l o g V ) O(VlogV) O(VlogV)。每次循环 D e c r e a s e − K e y Decrease-Key DecreaseKey O ( l o g V ) O(logV) O(logV),因为循环内每次更新都是针对边来说,所有边都遍历一遍,因此循环内总时间复杂度为 O ( E l o g V ) O(ElogV) O(ElogV),总时间复杂度为 T ( n ) = O ( ( V + E ) l o g V ) = O ( E l o g V ) T(n)=O((V+E)logV)=O(ElogV) T(n)=O((V+E)logV)=O(ElogV)

三、克鲁斯卡尔算法(Kruskal算法)

分析

  1. 从一个空图开始。
  2. 尝试一次添加一条边,始终确保所构建的保持无循环。.
  3. 如果我们在每一步都确定生成的图是某个最小生成树的子集,我们就完成了。

与Prim的算法生长一棵树不同,Kruskal的算法生长一组树(森林)。
最初,这个森林只由顶点组成(没有边)。
在每一步中,添加不产生循环的权重最小的边。
继续直到森林“合并”成一棵树。

本质上,也是继承于一说的主算法:
设A为Kruskal算法选择的边集,设(u, v)为下一步要添加的边。这足以说明这一点:
t h e r e there there i s is is a a a c u t cut cut t h a t that that r e s p e c t s respects respects A A A
( u , v ) (u, v) (u,v) i s is is t h e the the l i g h t light light e d g e edge edge c r o s s i n g crossing crossing t h i s this this c u t cut cut
在这里插入图片描述

算法流程

  1. 刚开始 A A A为空集, F F F存入所有边并且从小到大排序,
  2. 在F中选择一条权值最小的边e,检查将e加到A上是否形成一个循环。
    构成循环,则从F移除
    不构成循环,则从F添加进A
  3. F为空集时停止操作

现在有个问题,怎么才能不形成环呢,
在框架算法的每一步中, ( V , A ) (V,A) (V,A)都是非循环的,因此它是一个森林,一个顶点延申两条枝干,且枝干之间没有路径,这样就是森林。因此:
如果 u u u v v v在同一棵树中,则将边 u , v {u,v} u,v添加到A中创建一个循环。
如果 u u u v v v不在同一棵树中,那么将边 u , v {u,v} u,v添加到 A A A中不会创建一个循环。

根据这个性质,如果一条边被选中,它的两个端点若在一个树上,那么再将这条边添加进树时,肯定会形成环,根据这一性质,我们可以维护并查集去判断是否成环

并查集-Find-set

本质上,并查集就是一个个树集合,每个元素都唯一指向它的父亲,根节点父亲就是子集,因此每棵树的唯一标识就是根节点。如果两个元素唯一标识一样,那它们就在一棵树上。
在这里插入图片描述

j u d g e judge judge f i n d − s e t ( u ) find-set(u) findset(u) = = == == f i n d − s e t ( v ) find-set(v) findset(v),维护 f i n d − s e t find-set findset过程如下:

  1. C r e a t e − s e t u ) Create-set u) Createsetu):创建包含单个元素 u u u的集合。 O ( 1 ) O(1) O(1)
x.parent ← x
  1. F i n d − s e t ( u ) Find-set (u) Findset(u):查找包含元素u的集合(假设每个集合都有唯一的ID,后面可知是树的根节点)。 O ( l o g n ) O(logn) O(logn)
while x != x.parent do
	x ← x.parent
end
  1. U n i o n ( u , v ) Union(u, v) Union(u,v):将分别包含u和v的集合归并为一个公共集合。(当判断完不会形成环后,可以合并). O ( l o g n ) O(logn) O(logn)(找树的根节点费时,其他都是 O ( 1 ) O(1) O(1)时间)
    注意当我们将两棵树合并在一起时,我们总是将高树的根作为矮树的父树。不然会很畸形,费时。
    如果两棵树有相同的高度,我们选择第一棵树的根指向第二棵树的根。树的高度增加了1(根节点+被合并的子树,因此高度+1)。其他情况下树的高度都是不变的。
a ← Find-Set(x)
b ← Find-Set(y)
if a.height <= b.height then
	if a.height is equal to b.height then
		b.hright++;
	end
	a.parent ← b
end
else
	b.parent ← a
end

伪代码

sort E in increasing order by weight w;
A ← {}
for u ∈ V do
	Create-Set(u);
end
for ei ∈E do  //ei两个端点为ui,vi
	if(find-set(ui)!=find-set(vi)) then
		add {ui,vi} to A
		Union(ui,vi)
	end
end
return 

时间复杂度分析

排序用时 O ( E l o g E ) O(ElogE) O(ElogE) c r e a t e − s e t create-set createset用时 O ( V ) O(V) O(V),循环次数是边的次数 E E E,每次循环 u n i o n union union花费 l o g ( V ) log(V) log(V),总时间复杂度 O ( E l o g V ) O(ElogV) O(ElogV),因此总花费 T ( n ) = O ( E l o g E ) T(n)=O(ElogE) T(n)=O(ElogE)(边比顶点多,取大的)

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

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

相关文章

基于FactoryBean、实例工厂、静态工厂创建Spring中的复杂对象

&#x1f609;&#x1f609; 学习交流群&#xff1a; ✅✅1&#xff1a;这是孙哥suns给大家的福利&#xff01; ✨✨2&#xff1a;我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 &#x1f96d;&#x1f96d;3&#xff1a;QQ群&#xff1a;583783…

同旺科技 USB 转 RS-485 适配器

内附链接 1、USB 转 RS-485 适配器 基础版主要特性有&#xff1a;&#xff08;非隔离&#xff09; ● 支持USB 2.0/3.0接口&#xff0c;并兼容USB 1.1接口&#xff1b; ● 支持USB总线供电&#xff1b; ● 支持Windows系统驱动&#xff0c;包含WIN10 / WIN11系统32 / 64位…

基于Java SSM框架+Vue实现汉服文化平台网站项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架Vue实现汉服文化平台系统演示 摘要 本论文主要论述了如何使用JAVA语言开发一个汉服文化平台网站 &#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将…

Redis高可用集群架构

高可用集群架构 哨兵模式缺点 主从切换阶段&#xff0c; redis服务不可用&#xff0c;高可用不太友好只有单个主节点对外服务&#xff0c;不能支持高并发单节点如果设置内存过大&#xff0c;导致持久化文件很大&#xff0c;影响数据恢复&#xff0c;主从同步性能 高可用集群…

Java第二十章

一.创建线程 1.继承Thread类 Thread类是java.lang 包中的一个类&#xff0c;从这个类中实例化的对象代表线程&#xff0c;程序员启动一个新线程需要建立Thread实例。Thread类中常用的两个构造方法如下: public Thread()://创建一个新的线程对象。 public Thread(String threa…

王者荣耀游戏制作

1.创建所需要的包 2.创建怪物类 bear package beast;import wangzherogyao.GameFrame;public class Bear extends Beast {public Bear(int x, int y, GameFrame gameFrame) {super(x, y, gameFrame);setImg("img/bear.jpg");width 85;height 112;setDis(65);}} b…

倒计时 5 天,您有一份 2023 IoTDB 用户大会参会指南请注意查收!

叮叮&#xff01;距离 2023 IoTDB 用户大会在北京与大家见面还有 5 天&#xff01; 这场筹备已久的盛会&#xff0c;汇集了超 20 位大咖嘉宾带来的精彩议题&#xff0c;届时来自美国国家工程院、清华大学软件学院的产业大拿&#xff0c;与能源电力、钢铁冶炼、城轨运输、智能制…

如何使用ArcGIS Pro制作一张北极俯视地图

地图的表现形式有很多种&#xff0c;经常我们看到的地图是以大西洋为中心的地图&#xff0c;还有以太平洋为中心的地图&#xff0c;今天要给大家介绍的地图是从北极上方俯视看的地图&#xff0c;这里给大家讲解一下制作方法&#xff0c;希望能对你有所帮助。 修改坐标系 制作…

AntDB数据库:从海量数据处理,到5G计费商用核心

AntDB数据库自2008年研发面世以来&#xff0c;首先被应用于运营商的核心系统&#xff0c;满足运营商海量数据处理的需求。随着数字科技的不断发展&#xff0c;AntDB也在不断地更新迭代&#xff0c;逐渐地为更多行业与客户提供更全面的服务。5G时代来临&#xff0c;AntDB抓住发展…

webGL开发虚拟实验室

开发虚拟实验室是一个具有挑战性但也非常有趣和有价值的任务。通过 WebGL&#xff0c;你可以创建交互式、沉浸式的虚拟实验室&#xff0c;使用户能够进行实验和学习。以下是一些步骤和关键考虑因素&#xff0c;帮助你开始开发虚拟实验室&#xff0c;希望对大家有所帮助。北京木…

你知道显卡型号上的数字是什么意思吗?数字越大就越好吗?

大家好&#xff0c;欢迎来到我们的显卡探秘之旅&#xff01;今天&#xff0c;我们将一探究竟——显卡型号上的数字到底是啥意思&#xff1f;是不是数字越大&#xff0c;显卡就越NB&#xff1f;别急&#xff0c;跟着小编一起揭开这个神秘的数字面纱&#xff01; Q1 显卡的基本概…

技巧-PyCharm中Debug和Run对训练的影响和实验测试

简介 在训练深度学习模型时&#xff0c;使用PyCharm的Debug模式和Run模式对训练模型的耗时会有一些区别。 Debug模式&#xff1a;Debug模式在训练模型时&#xff0c;会对每一行代码进行监视&#xff0c;这使得CPU的利用率相对较高。由于需要逐步执行、断点调试、查看变量值等操…

链接共享平台LinkStack

什么是 LinkStack &#xff1f; LinkStack 是一个独特的平台&#xff0c;为在线管理和共享链接提供了高效的解决方案。平台提供了一个类似于 Linktree 的网站&#xff0c;它可以让用户克服社交媒体平台上只能添加一个链接的限制。借助 LinkStack&#xff0c;用户可以轻松链接到…

无需提前更新数据源,一键形态选股直接出票——股票量化分析工具QTYX-V2.7.3...

功能概述 我们的股票量化系统QTYX在实战中不断迭代升级!!! 星球学员中的大佬们给QTYX提供了很多实战应用方面的建议&#xff0c;志同道合的一群人一起来优化完善这个系统&#xff0c;日益强大的QTYX同时也能更好地帮助各位在市场中提高战绩&#xff01; 这个需求是来自于星球学…

“华为不造车 只帮车企造好车“ 那么华为到底造不造车

大家好&#xff0c;我是极智视界&#xff0c;欢迎关注我的公众号&#xff0c;获取我的更多前沿科技分享 邀您加入我的知识星球「极智视界」&#xff0c;星球内有超多好玩的项目实战源码和资源下载&#xff0c;链接&#xff1a;https://t.zsxq.com/0aiNxERDq "华为不造车&a…

W2311283-可燃气体监测仪怎么监测燃气管道

可燃气体监测仪怎么有效监测燃气管道 燃气管道遍布于城市地下各处&#xff0c;作为城市生命线的一部分&#xff0c;一旦燃气管网出现泄露问题便是牵一发而动全身&#xff0c;城市的整体安全也会受到威胁。但是如何才能科学管理和监测燃气管网呢&#xff1f; 燃气管网监测系统便…

Vue3-ElementPlus按需导入

1.安装 pnpm add element-plus 2.配置按需导入&#xff1a; 官方文档&#xff1a;快速开始 | Element Plus 按照官网按需导入中的自动导入步骤来进行 pnpm add -D unplugin-vue-components unplugin-auto-import 观察Vite代码与原vite文件的差别&#xff0c;将原vite文件中没…

实测有效的 8 个顶级Android 数据恢复工具

由于我们现在生活在一个依赖数字数据的时代&#xff0c;当重要文件从我们的 Android 手机中消失时&#xff0c;这将是一场数字噩梦。如果您没有预先备份Android手机上的数据或未能通过备份找到已删除的数据&#xff0c;那么选择最好的Android数据恢复软件是最佳选择。 因此&am…

Vue3中props传参(多种数据类型传参方式)

在Vue3中&#xff0c;props接收的type类型有以下几种&#xff1a; 1. String&#xff1a;字符串类型 2. Number&#xff1a;数字类型 3. Boolean&#xff1a;布尔类型 4. Array&#xff1a;数组类型 5. Object&#xff1a;对象类型 6. Date&#xff1a;日期类型 7. Func…

逻辑漏洞 暴力破解(DVWA靶场)与验证码安全 (pikachu靶场) 全网最详解包含代码审计

逻辑漏洞 暴力破解(DVWA靶场)与验证码安全 (pikachu靶场) 全网最详解包含代码审计 0x01 前言 在当今互联网的广袤世界中&#xff0c;各式交互平台层出不穷。每一个交互平台几乎都要求用户注册账号&#xff0c;而这些账号则成为我们在数字世界中的身份象征。账号的安全性变得至…