【第二十三课】最小生成树:prime 和 kruskal 算法(acwing858,859 / c++代码 )

目录

前言

Prime算法--加点法

acwing-858 

代码如下

一些解释 

Kruskal算法--加边法

acwing-859

并查集与克鲁斯卡尔求最小生成树 

代码如下

一些解释  


前言

之前学最短路的时候,我们都是以有向图为基础的,当时我们提到如果是无向图,只要记得两个顶点处都要加边就好了。

而在最小生成树的问题中,我们所面临的大多都是无向图。

这个姐姐👇对这两种算法的讲解非常清晰,没有代码部分,但是对于理解这两种算法的做法很有帮助,推荐看一下。 

【数据结构 图 最小生成树 Prime和Kruskal算法】

截取自视频。

感觉总结的很好,就搬过来啦(侵删) 

Prime算法--加点法

prime算法也叫加点法,主要是通过不断将所有顶点都加入到生成树中实现的。

利用该算法求最小生成树的步骤就是:

从任意1个顶点开始,在其他所有顶点中,选出一个离它距离最近的顶点,将其与该顶点进行连线;之后我们看其他的顶点中   离这两个已经选中的点  之间的距离最短的点,再将其连线......

由此我们可以总结出,我们要看的是:其他顶点中 到已经选出的这些顶点的集合 距离最短的点,我们把这个集合称为生成树,这里可以理解哈。

因此我们可以判断dist数组的含义应该是:存储每一个顶点到 集合(也就是生成树) 的最短距离。

prime算法的代码和dijkstra算法的实现是差不多的,主要区别就是dist数组的含义。前者是找离这个集合最短距离的点,后者找的是离某个源点距离最短的点

下面这个图模拟我们prime算法的手算的步骤

方便大家理解啦~ 

prime算法时间复杂度是O(n^2),适用于解决稠密图的问题。 

下面是模板题:

acwing-858 

可以看出数据范围边数远大于点数,属于稠密图。

与dijkstra算法的思路是差不多的,直接看代码把 

代码如下

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=510, INF=0x3f3f3f3f;
int n,m;
int g[N][N];
int dist[N];//存储每一个顶点到 集合(也就是生成树) 的最短距离
bool st[N];
int prime()
{memset(dist,0x3f,sizeof dist);int ans=0;for(int i=0;i<n;i++)//要加入所有的顶点,因此要循环n次{int t=-1;for(int j=1;j<=n;j++){if(!st[j] && (t==-1 || dist[t]>dist[j])){t=j;}}if(i && dist[t]==INF)return INF;if(i)ans+=dist[t];//第一个顶点权值是0,没必要再加一次,因此存在该if语句//选中t之后,比较原来的各个顶点到生成树的距离 与 各顶点与t顶点的权值的大小关系for(int j=1;j<=n;j++){dist[j]=min(dist[j],g[t][j]);}st[t]=1;}return ans;
}
int main()
{cin>>n>>m;memset(g,0x3f,sizeof g);for(int i=0;i<m;i++){int a,b,c;cin>>a>>b>>c;g[a][b]=g[b][a]=min(g[a][b],c);}int t=prime();if(t==INF)puts("impossible");else cout<<t<<endl;return 0;
}

一些解释 

1.if(i && dist[t]==INF)return INF; 

这里我们判断除了第一个顶点之外的其他顶点,到生成树的距离是否是无穷大,如果是无穷大说明图不连通,无法构成生成树

由于我们外层循环只控制循环次数,表示要加入n个顶点,且i从0开始,说明了第一个顶点是作为第0次循环实现的,因此这里排除第一个顶点,直接判断 i 就可以

为什么要跳过第一个顶点?

如果我们不跳过第一个顶点,那么在第一次循环时,由于所有顶点到生成树的距离都被初始化为无穷大,所以会直接返回无穷大,这显然是不正确的。因此,我们需要在第一次循环时跳过这个检查。

2.dist[j]=min(dist[j],g[t][j]); 

这里遍历各个顶点,判断 其原始的dist[j]与添加了 t 顶点之后,t与j顶点之间的权值 的大小关系,从而更新出每个顶点到生成树的距离。(因为既然t已经被加入到生成树中,那么到t的权值也就是到生成树的距离啦。)

把prime与dijkstra的代码放在一起对比一下

Kruskal算法--加边法

kruskal算法与prime对应是加边法,主要通过不断加边,连接到所有顶点之后就得到了最小生成树。

利用这种方法求最小生成树的步骤是:

在所有的边中不断的找最小的边加入到我们最小生成树的集合中,直到将所有顶点都连入。在加边过程中,避免成环即可。

曾经学数据结构的时候,手算我还是比较喜欢用克鲁斯卡尔算法的哈哈哈,感觉加边理解上好像更简单一点。

acwing-859

并查集与克鲁斯卡尔求最小生成树 

我们记得在并查集算法中,进行两个集合的合并和查找操作,就是利用树型结构实现的,在克鲁斯卡尔算法求最小生成树时,我们最终就是将顶点都连在一起算是得到了最小生成树,因此我们可以想着利用并查集的思想来实现克鲁斯卡尔求最小生成树。

嗯,,可以想一下二者的联系。我通过这样可以理解二者的关联。

下面是gpt的解释,更全面和专业一点hh,可以看看帮助理解一下~

应该是可以理解啦。 

需要的话可以回顾一下并查集的知识,之前写过哒

【第十四课】并查集(acwing-837连通块中点的数量 / c++代码 / 思路详解) 

代码如下

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2e5+10;
int n,m;
int p[N];
struct Edge{int a,b,w;//运算符重载函数bool operator< (const Edge &W)const{return w<W.w;}
}edges[N];
int find(int x)
{if(p[x]!=x)p[x]=find(p[x]);return p[x];
}
int main()
{cin>>n>>m;for(int i=0;i<m;i++){int a,b,w;cin>>a>>b>>w;edges[i]={a,b,w};}sort(edges,edges+m);//每个顶点都单独处在一个集合里for(int i=1;i<=n;i++)p[i]=i;int res=0,count=0;//res累加权值 count存储加入的边数for(int i=0;i<=m;i++)//遍历排好序的边的信息{int a=edges[i].a,b=edges[i].b,w=edges[i].w;a=find(a),b=find(b);//如果该边的两个顶点不连通 说明不会形成环if(a!=b){p[a]=b;res+=w;count++;}}if(count<n-1)puts("impossible");//如果边数并不符合 说明不存在最小生成树else cout<<res;return 0;
}

一些解释  

sort(edges,edges+m);

这里我们调用sort函数,直接写的edge结构体-edge+m,就是因为在结构体中我们定义了重载

//运算符重载函数bool operator< (const Edge &W)const{return w<W.w;}

因为结构体中含有多个变量,如果不定义运算符重载,那么在使用 sort 函数等需要比较边的权值大小的地方,编译器将无法确定如何比较两个 Edge 对象 。

关于重载的一些知识,,,


今年就先写到这里啦。大家除夕快乐啦~

有问题欢迎指出,一起加油!!

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

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

相关文章

复制和粘贴文本时剥离格式的5种方法(MacWindows)

您可能每天复制和粘贴多次。虽然它是一个非常方便的功能&#xff0c;但最大的烦恼之一就是带来了特殊的格式。从网络上获取一些文本&#xff0c;您经常会发现粘贴到文档中时&#xff0c;它保持原始样式。 我们将展示如何使用一些简单的技巧在不格式化的情况下复制和粘贴。 1.…

XSS-Lab

1.关于20关的payload合集。 <script>alert(1)</script> "><script>alert(1)</script> onclickalert(1) " onclick"alert(1) "><a href"javascript:alert(1)"> "><a HrEf"javascript:alert…

板块一 Servlet编程:第一节 HTTP协议理论与服务器请求响应原理 来自【汤米尼克的JAVAEE全套教程专栏】

板块一 Servlet编程&#xff1a;第一节 HTTP协议理论与服务器请求响应原理 一、HTTP特点二、HTTP中的 URL三、两种 HTTP 请求方法&#xff1a;GET 和 POST四、请求响应的底层请求头在服务器中表现响应头在服务器中表现 在上一个板块中我们完成了所有IDEA的基础配置工作&#xf…

9.0 Zookeeper 节点特性

本章节介绍一下 zookeeper 的节点特性和简单使用场景&#xff0c;正是由于这些节点特性的存在使 zookeeper 开发出不同的场景应用。 1、同一级节点 key 名称是唯一的 实例&#xff1a; $ ls / $ create /runoob 2 已存在 /runoob 节点&#xff0c;再次创建会提示已经存在。 …

APIfox自动化编排场景(二)

测试流程控制条件 你可以在测试场景中新增流程控制条件&#xff08;循环、判断、等待、分组&#xff09;等。进一步满足了更复杂的测试场景/流程配置的使用&#xff0c;最终借助自动化测试功能解决复杂场景的测试工作。 分组​ 当测试流程中多个步骤存在相关联关系时&#xf…

【Spring框架】Spring事务同步

目录 一、什么是Spring事务同步 二、 事务同步管理器 2.1 TransactionSynchronizationManager事务同步管理器 2.1.1 资源同步 2.1.2 事务同步 2.1.3 总结 三、事务同步管理器保障事务的原理 四、spring事务为何使用TransactionSynchronizationManager spring源码实现 …

【Linux】Shell编程

Shell编程 目录 Shell编程1.shell基础1.输入重定向 & 输出重定向2.管道3.特殊字符(3.1)通配符(3.2)引号(3.3)注释符(#) 4.别名5.命令历史history 2.Shell脚本Shell脚本的执行方式(1)为脚本文件加上可执行权限,然后在命令行直接输入shell脚本文件名执行。(2)sh shell脚本名(…

LabVIEW与EtherCAT实现风洞安全联锁及状态监测

LabVIEW与EtherCAT实现风洞安全联锁及状态监测 在现代风洞试验中&#xff0c;安全联锁与状态监测系统发挥着至关重要的作用&#xff0c;确保了试验过程的安全性与高效性。介绍了一套基于EtherCAT总线技术和LabVIEW软件开发的风洞安全联锁及状态监测系统。该系统通过实时、可靠…

SegmentAnything官网demo使用vue+python实现

一、效果&准备工作 1.效果 没啥好说的&#xff0c;低质量复刻SAM官网 https://segment-anything.com/ 需要提一点&#xff1a;所有生成embedding和mask的操作都是python后端做的&#xff0c;计算mask不是onnxruntime-web实现的&#xff0c;前端只负责了把rle编码的mask解…

Web Services 服务 是不是过时了?创建 Web Services 服务实例

Web Services 是不是过时了&#xff1f; 今天是兔年最后一天&#xff0c;先给大家拜个早年 。 昨天上午视频面试一家公司需要开发Web Services 服务&#xff0c;这个也没有什么&#xff0c;但还需要用 VB.net 开发。这个是多古老的语言了&#xff0c;让我想起来了 10年 前 写 …

Eclipse安装配置、卸载教程(Windows版)

Eclipse是一个开放源代码的集成开发环境&#xff08;IDE&#xff09;&#xff0c;最初由IBM公司开发&#xff0c;现在由Eclipse基金会负责维护。它是一个跨平台的工具&#xff0c;可以用于开发多种编程语言&#xff0c;如Java、C/C、Python、PHP、Rust等。 Eclipse提供了一个可…

Android AOSP源码研究之万事开头难----经验教训记录

文章目录 1.概述2.Android源下载1.配置环境变量2.安装curl3.下载repo并授权4.创建一个文件夹保存源码5.设置repo的地址并配置为清华源6.初始化仓库7.指定我们需要下载的源码分支并初始化 2.1 使用移动硬盘存放Android源码的坑2.2 解决方法 3.Android源码编译4.Android源烧录 1.…

MySQL篇之回表查询

一、聚集索引 将数据存储与索引放到了一块&#xff0c;索引结构的叶子节点保存了行数据。特点&#xff1a;必须有,而且只有一个。 聚集索引选取规则: 1. 如果存在主键&#xff0c;主键索引就是聚集索引。 2. 如果不存在主键&#xff0c;将使用第一个唯一&#xff08;UNIQUE&am…

【开源】基于JAVA+Vue+SpringBoot的智慧社区业务综合平台

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 业务类型模块2.2 基础业务模块2.3 预约业务模块2.4 反馈管理模块2.5 社区新闻模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 业务类型表3.2.2 基础业务表3.2.3 预约业务表3.2.4 反馈表3.2.5 社区新闻表 四、系统展…

深入解析Elasticsearch的内部数据结构和机制:行存储、列存储与倒排索引之行存(一)

在当今的大数据时代&#xff0c;高效的数据检索和分析能力已成为许多应用程序的核心需求。Elasticsearch&#xff0c;作为一款强大的分布式搜索和分析引擎&#xff0c;正是为了满足这些需求而诞生的。它之所以能够在海量数据中实现毫秒级的搜索响应&#xff0c;以及灵活的数据分…

Docker进阶篇-CIG重量级监控系统

一、简介 通过docker stats命令可以很方便的查看当前宿主机上所有容器的CPU、内存、网络流量等数 据&#xff0c;可以满足一些小型应用。 但是docker stats统计结果只能是当前宿主机的全部容器&#xff0c;数据资料是实时的&#xff0c;没有地方存储、 没有健康指标过线预警…

肯尼斯·里科《C和指针》第13章 高级指针话题(3)命令行参数

处理命令行参数是指向指针的指针的另一个用武之地。有些操作系统&#xff0c;包括UNIX和MS-DOS&#xff0c;让用户在命令行中编写参数来启动一个程序的执行。这些参数被传递给程序&#xff0c;程序按照它认为合适的任何方式对它们进行处理。 13.4.1 传递命令行参数 这些参数如何…

html5 audio video

DOMException: play() failed because the user didn‘t interact with the document first.-CSDN博客 不可用&#xff1a; 可用&#xff1a; Google Chrome Close AutoUpdate-CSDN博客

用HTML5实现灯笼效果

本文介绍了两种实现效果&#xff1a;一种使用画布&#xff08;canvas&#xff09;标签/元素&#xff0c;另一种不用画布&#xff08;canvas&#xff09;标签/元素主要使用CSS实现。 使用画布&#xff08;canvas&#xff09;标签/元素实现&#xff0c;下面&#xff0c;在画布上…

Compose | UI组件(十四) | Navigation-Data - 页面导航传递数据

文章目录 前言传参流程实例说明普通方式传值定义接受参数格式定义接受参数类型获取参数传入参数传参和接受参数效果图 结合 ViewModel 传递参数定义ViewModel在 navigation 定义 ViewModel 实例&#xff0c;并且传入 LoginScreen传入输入框中的值&#xff0c;并且跳转传值获取值…