【第二十二课】最短路: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…

1484. 按日期分组销售产品

说在前面 &#x1f388;不知道大家对于算法的学习是一个怎样的心态呢&#xff1f;为了面试还是因为兴趣&#xff1f;不管是出于什么原因&#xff0c;算法学习需要持续保持。 题目描述 表 Activities&#xff1a; ---------------------- | 列名 | 类型 | --------…

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;这些文件共同组…

Steam爆火游戏幻兽帕鲁自建多人联机专用服务器配置要求

《幻兽帕鲁》这款多人游戏模式的全新开放世界生存制作游戏&#xff0c;在短短上线5天就卖出700万份&#xff0c;同时在线人数最高达到了180万人&#xff0c;创下Steam历史榜单第二名的好成绩&#xff0c;意料之外的爆火也一度导致幻兽帕鲁出现无法创建4人游戏房间、官方服务器连…

C语言-算法-最短路

【模板】Floyd 题目描述 给出一张由 n n n 个点 m m m 条边组成的无向图。 求出所有点对 ( i , j ) (i,j) (i,j) 之间的最短路径。 输入格式 第一行为两个整数 n , m n,m n,m&#xff0c;分别代表点的个数和边的条数。 接下来 m m m 行&#xff0c;每行三个整数 u …

VUE3:组合式API生命周期

1、onMounted 注册一个回调函数&#xff0c;在组件挂载完成后执行。 组件在以下情况下被视为已挂载&#xff1a; – 1. 其所有同步子组件都已经被挂载。 – 2. 其自身的 DOM 树已经创建完成并插入了父容器中。注意仅当根容器在文档中时&#xff0c;才可以保证组件 DOM 树也在文…

已定式,未定式【高数笔记】

【已定式】 将x-->? 的过程代入到lim中&#xff0c;如果得出的结果可以判断出&#xff0c;lim是有极限的&#xff0c;则为已定式 [举例] lim(1/x)&#xff0c;x--> 无穷 &#xff0c;即&#xff0c;1/ 无穷 0 &#xff0c;所以为已定式 【未定式】 将x-->? 的过程代…

docker 搭建 Seafile 集成 onlyoffice

docker-compose一键部署yaml文件 version: "3"services:db:image: mariadb:10.11container_name: seafile-mysqlenvironment:- MYSQL_ROOT_PASSWORDdb_dev # Requested, set the roots password of MySQL service.- MYSQL_LOG_CONSOLEtruevolumes:- /share/ZFS18_D…

Rust - 变量

不管学什么语言好像都得从变量开始&#xff0c;不过只需要懂得大概就可以了。 但在Rust里不先把变量研究明白后面根本无法进行… 变量绑定 变量赋值❌ 变量绑定✔️ Rust中没有“赋值”一说&#xff0c;而是称为绑定。 int a 3; //C中的变量赋值 a 3; //python中的…

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

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

transformer_多头注意力机制代码笔记

transformer_多头注意力机制代码笔记 以GPT-2中多头注意力机制代码为例 class CausalSelfAttention(nn.Module):"""因果掩码多头自注意力机制A vanilla multi-head masked self-attention layer with a projection at the end.It is possible to use torch.nn…

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

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