U4_2:图论之MST/Prim/Kruskal

文章目录

  • 一、最小生成树-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.mfbz.cn/a/199372.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

局域网协议:ICMP (Internet Control Message Protocol,互联网控制消息协议)

ICMP&#xff08;Internet Control Message Protocol&#xff0c;互联网控制消息协议&#xff09;是用于在IP网络中传递控制消息的协议。它通常被用于网络设备之间交换状态信息和错误报告&#xff0c;以及执行网络诊断和故障排除。 文章目录 ICMP主要功能ICMP的工作原理ICMP消…

python之pyqt专栏7-信号与槽3

在上一篇文章中python之pyqt专栏6-信号与槽2-CSDN博客中&#xff0c;我们可以了解到对象可以使用内置信号&#xff0c;这些信号来自于类定义或者继承过来的。我们可以对这些信号可以通过connect连接槽函数。 需求 现在有一个需求&#xff0c;有两个UI界面“untitled.ui”和“u…

css-tricks网站图例

使用css实现钟表 <template><div><p><small>CSS sin() and cos() does <strong>NOT</strong> work in your browser.</small></p><div class"clock"><div id"app" class"clock-face"…

如何恢复已删除的照片 ?适用于 Windows 的Android 数据恢复软件值得尝试

“我丢失了 Android 手机上的照片&#xff0c;有人告诉我使用恢复程序来找回所有手机数据。我使用的是 Windows 10 和华为 手机&#xff0c;对于 Windows最有效的 Android 数据恢复是什么&#xff1f;” Android 恢复程序用于检索丢失或删除的文件&#xff0c;如照片、联系人、…

城市生命线中城市内涝积水监测系统设计与应用

近年来&#xff0c;城市内涝问题日益凸显&#xff0c;给城市安全和居民生活带来严重威胁。为了解决这一问题&#xff0c;云南省水网建设规划提出了一系列的防涝措施&#xff0c;其中包括城市内涝积水监测系统的建设。 城市内涝积水监测系统作为城市生命线中之一&#xff0c;在城…

Spring Cloud 版本升级记:OpenFeignClient与Gateway的爱恨交织

Spring Cloud 版本升级记&#xff1a;OpenFeignClient与Gateway的爱恨交织 近日&#xff0c;在负责的项目中&#xff0c;我对 Spring Boot、Spring Cloud 以及 Spring Cloud Alibaba 进行了版本升级。原以为会一切顺利&#xff0c;没想到却遭遇了 Spring Cloud Gateway 无法正…

从赛车到服务台:IT团队可以从F1赛车中学到什么?

一级方程式赛车被誉为最高级别的赛车&#xff0c;简称F1赛车&#xff0c;它不断挑战速度、创新和进步的极限。因此&#xff0c;对于您的IT团队来说&#xff0c;还有什么比这项运动更值得借鉴的呢&#xff1f; 作为赛车运动的巅峰之作&#xff0c;F1赛车拥有10支车队和20名车手…

LLM、ChatGPT与多模态必读论文150篇

为了写本 ChatGPT 笔记&#xff0c;我和10来位博士、业界大佬&#xff0c;在过去半年翻了大量中英文资料/paper&#xff0c;读完 ChatGPT 相关技术的150篇论文&#xff0c;当然还在不断深入。 由此而感慨&#xff1a; 读的论文越多&#xff0c;你会发现大部分人对ChatGPT的技…

因为计算机中丢失MSVCP140.dll,无法启动此程序运行软件的解决方法

msvcp140.dll重新安装五个解决方法与msvcp140.dll文件的作用和丢失对电脑的影响介绍 正文&#xff1a; 在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中最常见的就是“缺少xxx.dll文件”。而msvcp140.dll就是其中之一。那么&#xff0c;msvcp140.…

anaconda换源安装pytorch(附带bug解决办法)

1.安装anaconda 如何安装anaconda可以看这篇文章:如何安装anaconda 2.换源安装pytorch: 首先进入到pytorch官网&#xff0c;选对好参数之后复制命令进入到anaconda prompt即可: 然后进入自己的环境之后输入该命令(即conda install …)&#xff0c;则可以进行下载。下载完成…

物理世界中的等距3D对抗样本

论文题目&#xff1a;Isometric 3D Adversarial Examples in the Physical World 会议&#xff1a;NIPS 2022 点云&#xff1a; 点云——表达目标空间分布和目标表面特性的海量点集合&#xff0c;点包含xyz坐标信息 能够包含颜色等其他信息 使用顶点、边和面的数据表征的三维…

2 线、3 线和 4 线 RTD 配置之间有什么区别?

电阻温度检测器 (RTD) 是温度传感器的一种&#xff0c;由于其准确性、可重复性和稳定性而广泛应用于各种工业应用。这些设备通过感测材料温度变化时电阻的变化来测量温度。 RTD 探头有多种配置&#xff0c;包括 2 线、3 线和 4 线型号。这些类型之间存在显着差异&#xff0c;在…

Mysql更新varchar存储的Josn数据

Mysql更新varchar存储的Josn数据 记录一次mysql操作varchar格式存储的json字符串数据 1、检查版本 -- 版本5.7以上才可以能执行json操作 select version(); 2、创建测试数据 -- 创建测试表及测试数据 CREATE TABLE test_json_table AS SELECT UUID(), {"test1": …

博客RESTful API 接口开发

目录 1.博客系统规划 2.基础服务搭建 3.登录接口 4.新增文章接口 5.查询文章接口 6.修改文章接口 7.删除文章接口 总结 1.博客系统规划 首先规划一下有哪些接口&#xff0c;从博客文章角度来看&#xff0c;需要如下接口&#xff1a; 新增文章接口&#xff0c;传递…

蓝桥杯第一天-----时间显示

文章目录 前言一、题目描述二、测试用例三、题目分析四、具体代码实现总结 前言 本章中将相信介绍蓝桥杯中关于时间显示的题目。 链接&#xff1a;https://www.lanqiao.cn/problems/1452/learning/ 一、题目描述 二、测试用例 三、题目分析 1.输入的时间为毫秒&#xff0c;毫…

蓝桥杯每日一题2023.11.28

题目描述 三羊献瑞 - 蓝桥云课 (lanqiao.cn) 题目分析 本题首先进行观察可以确定 1.“三”为 1 &#xff08;十进制数字要进位进一位&#xff09; 2.“祥”一定不为 0 &#xff08;有前导0就不能算为 4 位数&#xff09; 使用搜索时将其特判 #include<bits/stdc.h> …

Matplotlib直方图的创建_Python数据分析与可视化

Matplotlib直方图的创建 概念区分绘制直方图 概念区分 什么是直方图&#xff1f; 直方图&#xff08;Histogram&#xff09;又称质量分布图&#xff0c;是统计报告图的一种&#xff0c;由一系列高度不等的纵向条纹或线段表示数据分布的情况&#xff0c;一般用横轴表示数据所属…

基于YOLOv8深度学习的行人跌倒检测系统【python源码+Pyqt5界面+数据集+训练代码】目标检测

基本功能演示 摘要&#xff1a;跌倒是一种常见的意外事件&#xff0c;尤其对于老年人、儿童、孕妇以及患有某些疾病的人群来说&#xff0c;跌倒可能会导致严重的身体损伤甚至危及生命。因此&#xff0c;及时准确地检测跌倒事件&#xff0c;对于保护人们的生命安全&#xff0c;提…

list简单使用

目录 介绍 头文件 简单使用 Member functions Constructor operator ​编辑 Iterators Capacity empty size Element access: front/back Modifiers push_front pop_front push_back pop_back insert erase swap resize clear Operations remove uniq…

分享一个适用于 Vue3 的好的组件库,PrimeVue组件。

一、PrimeVue介绍 PrimeVue 是一个基于 Vue.js 的 UI 组件库&#xff0c;专注于提供丰富、灵活、现代的 UI 组件&#xff0c;以帮助开发者构建功能强大的 Web 应用程序。PrimeVue 提供了一系列的组件&#xff0c;涵盖了从基本的表单元素到高级的数据表格和图表等各种组件。 二、…
最新文章