【第二十二课】最短路:dijkstra算法 ( acwing849 / acwing850 / c++ 代码)

目录

dijkstra算法求最短距离步骤

朴素的dijkstra算法---acwing-849

代码如下

代码思路 

堆优化版的dijkstra算法---acwing-850

代码如下


关于最短路问题分有好几种类型 :

单源就是指:只求从一个顶点到其他各顶点

多源是指:要求每个顶点到其他各顶点 

这些情况对应有不同的算法,这次先介绍dijkstra算法的两种。 

dijkstra算法求最短距离步骤

我们手写的步骤就是:

1.

确定我们要处理的单源点。即我们是想 从哪个顶点开始寻找到其他顶点的最短路径。

2.

第一轮:看该顶点到其他任意顶点的距离并记录下来。一般只有直连的顶点是边的权重,其他不直连的都是正无穷,每个顶点都看过之后,选出这些记录下来的距离的最小值所对应的顶点编号。

3.

相当于第二轮的时候,我们可以看作,起始顶点是上一轮选出的最小距离的顶点,且起步价就是初始值是这个最小距离。由此不断迭代直到寻找过所有顶点到开始顶点的最短距离。【我觉得这种思路比较好理解,对应下面视频讲解的第二个】

 如下图 (INF表示的是正无穷)

关于该算法的一些视频讲解的推荐:

 【图-最短路径-Dijkstra(迪杰斯特拉)算法】

【【全网第二清晰】手写迪杰斯特拉-Dijkstra(考试用)】

讲的都很清晰,可以看一下

朴素的dijkstra算法---acwing-849

代码如下

步骤明白之后代码的含义需要解释的都写在注释里了。 

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=510;
int n,m;
int g[N][N];//用邻接矩阵来存储稠密图,二维数组的每一位表示【行标指向列标的边 所对应的权重】
int dist[N];//存储从起点到其他节点当前的最短距离
bool st[N];//标记该点是否已经已经被寻找过int dijkstra()
{memset(dist,0x3f,sizeof dist);//初始状态所有的距离都是正无穷dist[1]=0;//习惯将节点从1开始编号,且本题求的就是1节点到其他节点的最短距离。该点到其自身的距离为0//确保了寻找了每个节点到源节点的最短路径for(int i=0;i<n;i++){int t=-1;// 用于标记当前轮次中【距离最短的未访问节点的编号】,初始化为 -1 表示尚未找到有效节点for(int j=1;j<=n;j++){if(!st[j] && (t==-1 || dist[t]>dist[j])){t=j;//找到当前轮次中距离最短的未访问节点的编号}}st[t]=1;//找到后将其标记为1//通过选定的节点更新到其他节点的最短距离for(int j=1;j<=n;j++){dist[j]=min(dist[j],dist[t]+g[t][j]);//g[t][j]表示经过节点t到达节点j的路径长度}}if(dist[n]==0x3f3f3f3f)return -1;return dist[n];
}
int main()
{cin>>n>>m;memset(g,0x3f,sizeof g);while(m--){int a,b,c;cin>>a>>b>>c;g[a][b]=min(g[a][b],c);//面对多重边的情况 取权值小的边}int t=dijkstra();cout<<t;return 0;
}

代码思路 

1.根据题目中的数据范围,边数远远大于顶点数,因此是稠密图,且用邻接矩阵存储图。 而这里每条边都会有各自权值,因此用邻接矩阵加边直接更改二维数组中对应位置为对应权重即代表了存在权值为x的边不用单独写添加边的函数。

2.求1->n任意一个顶点的最短距离,使用dijkstra算法。单独分装函数,函数内部也就是代码实现该算法的步骤。

3.dijkstra函数内部。首先初始化dist数组值为正无穷。注意dist数组的含义是:下标表示顶点,该数组表示下标对应的顶点距起始顶点的最短距离。由于我们是从1号顶点开始,且其自身到自身的距离应该是0,由此初始dist[1]=0 ;

之后就开始经过n轮寻找,确保每一个顶点都进行了寻找,因此外层循环次数为n次。由于只是控制次数,所以从0~n-1的循环条件是可以的,当然也可以写1~n

需要创建一个st数组做标记,标记那些已经找到最短距离的点。下标表示点的编号。

每次寻找需要做什么?观察所有顶点(内层for循环),找到距离源点距离最短的顶点,标记该顶点已经找到最短距离,之后遍历所有顶点,更新最短距离,看加了这个点之后其他有没有哪个点有更优的最短距离,进行更改即可。

这段代码的时间复杂度最差是O(n^2),与边数m无关,因此适用于稠密图。 

堆优化版的dijkstra算法---acwing-850

这道题的区别就是n和m的取值范围是相同的,都是1.5e5 ,该图为稀疏图。首先不同的就是这道题会采用邻接表存储图。

代码上的不同主要就是:利用堆来简化循环的嵌套,降低时间复杂度。

之前写的关于堆的文章,可以回顾一下。

手写堆

【第十五课】数据结构:堆 (“堆”的介绍+主要操作 / acwing-838堆排序 / 时间复杂度的分析 / c++代码 )

【第十五课】数据结构:堆(acwing-839模拟堆 / ph和hp数组的映射关系 /c++代码 )

stl优先队列

【第十七课】c++常用的STL容器

代码如下

我们这里使用优先队列实现。 

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>//使用优先队列
using namespace std;
typedef pair<int,int> PII;//第一个元素表示最短距离,第二个元素表示顶点编号
const int N=1.5e5+10;
int n,m;
int h[N],e[N],ne[N],w[N],idx;
int dist[N];//存储从起点到其他节点当前的最短距离
bool st[N];//标记该点是否已经被处理过void add(int a,int b,int c)
{e[idx]=b;ne[idx]=h[a];w[idx]=c;h[a]=idx++;
}
int dijkstra()
{memset(dist,0x3f,sizeof dist);//初始状态所有的距离都是正无穷dist[1]=0;//习惯将节点从1开始编号,且本题求的就是1节点到其他节点的最短距离。该点到其自身的距离为0priority_queue<PII,vector<PII>,greater<PII>> he;//创建小根堆he.push({0,1});//先将源点加入队列while(he.size())//当队列不为空{PII t=he.top();he.pop();//将当前的最短距离出队int ver=t.second,distance=t.first;//ver表示顶点 distance表示最短距离if(st[ver])continue;//如果这个顶点已经处理过就直接跳过for(int i=h[ver];i!=-1;i=ne[i])//遍历这个点的所有直连的边{int j=e[i];if(dist[j]>distance+w[i])//更新与其直连的点的最短距离{dist[j]=distance+w[i];he.push({dist[j],j});}}}if(dist[n]==0x3f3f3f3f)return -1;return dist[n];
}
int main()
{cin>>n>>m;memset(h,-1,sizeof h);while(m--){int a,b,c;cin>>a>>b>>c;add(a,b,c);}int t=dijkstra();cout<<t;return 0;
}

注意这里其实并没有处理重边,这是因为:我们是按照逐个顶点遍历其所连的边处理的,对于重边我们会和该顶点的其他边一样,进行平等的判断,得出一个最短距离的边只有最短的边会在当前阶段影响最短路径

使用优先队列所优化的是求最短距离这一步,本来需要遍历所有节点,找到离源点距离最小的点,时间复杂度为 O(n),通过优先队列实现小根堆,堆顶是最小值,直接将这一步优化为O(1)


感觉堆优化版的更好理解一点,,朴素的做法每层循环的功能要搞明白,清楚执行的什么操作。

好啦先写到这里。

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

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

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

相关文章

SD-WAN和MPLS的区别以及如何选择?

网络连接技术的选择对企业来说至关重要。SD-WAN&#xff08;软件定义广域网&#xff09;和MPLS&#xff08;多协议标签交换&#xff09;是两种备受关注的网络连接方案。它们在架构、带宽、成本和管理等方面存在显著区别&#xff0c;企业应了解清楚这些区别再进行选择。 SD-WAN采…

AI算力专题:从超微电脑创新高看AI算力产业链高景气

今天分享的是AI算力系列深度研究报告&#xff1a;《AI算力专题&#xff1a;从超微电脑创新高看AI算力产业链高景气》。 &#xff08;报告出品方&#xff1a;太平洋证券&#xff09; 报告共计&#xff1a;10页 海外巨头指引 Al 算力产业链高景气 超微电脑业绩指引大幅上调反映…

三子棋游戏小课堂

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 今天的主菜是&#xff0c;C语言实现的三子棋小游戏&#xff0c; 所属专栏&#xff1a; C语言知识点 主厨的主页&#xff1a;Chef‘s blog 前言&…

机器学习 | 掌握逻辑回归在实践中的应用

目录 初识逻辑回归 逻辑回归实操 分类评估方法 初识逻辑回归 逻辑回归&#xff08;LogisticRegression&#xff09;是机器学习中的一种分类模型&#xff0c;逻辑回归是一种分类算法&#xff0c;虽然名字中带有回归&#xff0c;但是它与回归之间有一定的联系。由于算法的简单…

【Spark系列2】Spark编程模型RDD

RDD概述 RDD最初的概述来源于一片论文-伯克利实验室的Resilient Distributed Datasets&#xff1a;A Fault-Tolerant Abstraction for In-Memory Cluster Computing。这篇论文奠定了RDD基本功能的思想 RDD实际为Resilient Distribution Datasets的简称&#xff0c;意为弹性分…

【大厂AI课学习笔记】1.3 人工智能产业发展(2)

&#xff08;注&#xff1a;腾讯AI课学习笔记。&#xff09; 1.3.1 需求侧 转型需求&#xff1a;人口红利转化为创新红利。 场景丰富&#xff1a;超大规模且多样的应用场景。主要是我们的场景大&#xff0c;数据资源丰富。 抗疫加速&#xff1a;疫情常态化&#xff0c;催生新…

Windows11通过Hyper-V创建VM,然后通过vscode连接vm进行开发

这边需要在win11上建立vm来部署docker(这边不能用windows版本的docker destop)&#xff0c;学习了下&#xff0c;记录。 下载系统镜像 首先下载系统镜像&#xff1a;https://releases.ubuntu.com/focal/ 这边使用的是ubuntu20.04.6 LTS (Focal Fossa) &#xff0c;Server inst…

CIFAR-10数据集详析:使用卷积神经网络训练图像分类模型

1.数据集介绍 CIFAR-10 数据集由 10 个类的 60000 张 32x32 彩色图像组成&#xff0c;每类 6000 张图像。有 50000 张训练图像和 10000 张测试图像。 数据集分为5个训练批次和1个测试批次&#xff0c;每个批次有10000张图像。测试批次正好包含从每个类中随机选择的 1000 张图像…

易优CMS采集插件使用教程

本易优CMS采集教程说明如何使用易优CMS采集插件&#xff0c;批量获取互联网上的文章数据&#xff0c;并自动更新到易优cms&#xff08;eyoucms&#xff09;网站&#xff0c;快速丰富网站的内容。 目录 1. 下载并安装易优CMS采集插件 2. 对接网页文章采集工具 3. 采集数据发…

GPT-4级别模型惨遭泄露!引爆AI社区,“欧洲版OpenAI”下场认领

大家好&#xff0c;我是二狗。 这两天&#xff0c;一款性能接近GPT-4的模型惨遭泄露&#xff0c;引发了AI社区的热议。 这背后究竟是怎么回事呢&#xff1f; 起因是1月28日&#xff0c;一位名为“Miqu Dev”的用户在 HuggingFace 上发布了一组文件&#xff0c;这些文件共同组…

智慧工地可视化综合管理云平台 PC+APP

目录 一、智慧工地可视化数据大屏功能一览 1.首页 2.视频监控 3.机械设备 4.环境监测 5.安全管理 6.质量管理 7.劳务分析 8.进度管理 9.报警统计 二、项目人员管理 1.信息管理 2.信息采集 3.证件管理 危大工程管理 一、智慧工地可视化数据大屏功能一览 包括&am…

【C语言】const修饰指针的不同作用

目录 const修饰变量 const修饰指针变量 ①不用const修饰 ②const放在*的左边 ③const放在*的右边 ④*的左右两边都有const 结论 const修饰变量 变量是可以修改的&#xff0c;如果把变量的地址交给⼀个指针变量&#xff0c;通过指针变量的也可以修改这个变量。 但…

电脑文件打不开是什么原因?常见原因有这9点

在日常生活和工作中&#xff0c;我们经常会使用电脑来处理文件。然而&#xff0c;有时候我们会遇到电脑文件打不开的情况&#xff0c;这给我们的工作和生活带来了很大的不便。本文将为大家介绍电脑文件打不开的原因&#xff0c;帮助大家更好地应对这一问题。 原因1、文件格式问…

论文解读:DeepBDC小样本图像分类

Joint Distribution Matters: Deep Brownian Distance Covariance for Few-Shot Classification 摘要 由于每个新任务只给出很少的训练样例&#xff0c;所以few -shot分类是一个具有挑战性的问题。解决这一挑战的有效研究路线之一是专注于学习由查询图像和某些类别的少数支持…

shell脚本自动备份数据库表

今日目标&#xff1a;shell脚本自动备份数据库中的表并记录执行日志和mysql输出日志 编写思路&#xff1a; &#xff08;1&#xff09;shell脚本运行mysql命令 &#xff08;2&#xff09;脚本输出记录到日志中 &#xff08;3&#xff09;定时任务自动执行shell脚本 1、she…

【Tomcat与网络9】提高Tomcat启动速度的八大措施

本文我们来看一下如何对Tomcat进行调优&#xff0c;我们对于Tomcat的调优主要集中在三个方面&#xff1a;提高启动速度、提高系统稳定性和提高并发能力&#xff0c;后两者很多时候是相辅相成的&#xff0c;我们放在一起看。 Tomcat现在一般都嵌入在SpringBoot里&#xff0c;因…

Linux 驱动开发基础知识——总线设备驱动模型(八)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;Vir2021GKBS &#x1f43c;本文由…

动网格-尺寸函数耦合运动(五)

尺寸函数 **尺寸函数(Size Function)**通常和局部体网格重构结合使用&#xff0c;尺寸函数用于控制重构过程中的网格分布。简单地说&#xff0c;尺寸函数的功能就是在运动边界处约束网格&#xff0c;使其维持在一个较小的尺度&#xff0c;在远离运动边界处&#xff0c;逐步将其…

Windows存储空间不足局域网文件共享 Dism备份系统空间不足

问题情景 在日常使用中难免遇到Windows的空间不足的情况&#xff0c;常用办法是清理垃圾释放空间&#xff0c;部分场景例如我们需要使用Dism备份完整系统&#xff0c;所以需要非常大的存储空间不够&#xff0c;如果空间不够什么才是最有效的方案呢&#xff1f; 我们假设身边没有…

如何使用docker部署Swagger Editor并实现无公网ip远程协作编辑文档

文章目录 Swagger Editor本地接口文档公网远程访问1. 部署Swagger Editor2. Linux安装Cpolar3. 配置Swagger Editor公网地址4. 远程访问Swagger Editor5. 固定Swagger Editor公网地址 Swagger Editor本地接口文档公网远程访问 Swagger Editor是一个用于编写OpenAPI规范的开源编…