Dijkstra求最短路 I(Dijkstra算法)

给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环,所有边权均为正值。

请你求出 1 号点到 n 号点的最短距离,如果无法从 1 号点走到 n 号点,则输出 −1。

输入格式

第一行包含整数 n 和 m。

接下来 m 行每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。

输出格式

输出一个整数,表示 1 号点到 n 号点的最短距离。

如果路径不存在,则输出 −1。

数据范围

1≤n≤500,
1≤m≤10^5,
图中涉及边长均不超过10000。

输入样例:
3 3
1 2 2
2 3 1
1 3 4
输出样例:
3

思路:

最短路问题,可以用dijkstra算法来解决,这里是解决各种最短路问题的框架

因为这道题求的是单源最短路,且每条路权值都为正数,并且边的量级明显大于点(1≤n≤500,
1≤m≤10^5),是稠密图,所以用朴素dijkstra算法解决

朴素dijkstra算法的原理:

初始化,除了起点之外,每个点到起点的距离为无穷大。我们创建一个集合s,表示当前已确定最短距离的点,对于n个点,循环n次,每次找到一个不在集合s中的离起点(题目中的1号点)最近的点,然后将它加入集合s,并用这个点去更新其他所有点距离。

const int N=510;
int n,m;
int g[N][N];  //题目中是稠密图,用邻接矩阵写,g[1][2]表示从1节点指向2节点的距离
int dist[N];  //从1号点走到每个点的距离(最短距离)
bool st[N];  //每个点最短路是否已经确定,true为确定

因为是稠密图,所以我们用邻接矩阵g[ ][ ]存储边和点的关系。

   for(int i=0;i<n;i++) //迭代n次,每次做两件事:1.找到集合外到起点最短距离的点 2.用这个点来更新到其他点的最短距离{int t=0;  //t表示当前要找的集合外到起点最短距离的点,0表示初始化for(int j=1;j<=n;j++) //第一轮循环,寻找集合外到起点最短距离的点,一开始1号点也是在集合外的,所以j从1开始找{//找当前不确定最短距离的点集合外(即st为false)到起点距离最短的点if(!st[j] && (dist[t]>dist[j])) //当前点最短路还没被确定并且当前t不是最短的,一开始的d[t]是无穷,d[1]是0,所以1号点就会找到{t=j; //换成短的那条路 }}st[t]=true;  //找到了集合外到起点最短距离的点,标记(其实就是加入了确定最短距离的集合)for(int j=1;j<=n;j++) //第二轮循环,用已经确定了的最短距离的点来更新到其他点的最短距离{dist[j]=min(dist[j],dist[t]+g[t][j]); //更新1到j这条路的长度(从1到t,再从t到j的距离与1到j距离比较,换成短的那条路)}      }

dijkst算法的核心代码,进行n次循环,每次循环找到集合外到起点最短距离的点 ,然后用这个点来更新到其他点的最短距离。

        for(int j=1;j<=n;j++) //第一轮循环,寻找集合外到起点最短距离的点,一开始1号点也是在集合外的,所以j从1开始找{//找当前不确定最短距离的点集合外(即st为false)到起点距离最短的点if(!st[j] && (dist[t]>dist[j])) //当前点最短路还没被确定并且当前t不是最短的,一开始的d[t]是无穷,d[1]是0,所以1号点就会找到{t=j; //换成短的那条路 }}st[t]=true;  //找到了集合外到起点最短距离的点,标记(其实就是加入了确定最短距离的集合)

经过第一次循环后,我们找到了一个点t,将它加入集合s,这里每次t初始化为0,dist[0]=0x3f3f3f3f,保证了后面(dist[t]>dist[j])找到的是集合s外的点的第一个点,因为dist[t]是最大的(正无穷),所以遇到的第一个没加入集合s的点就会被加入集合s。

        for(int j=1;j<=n;j++) //第二轮循环,用已经确定了的最短距离的点来更新到其他点的最短距离{dist[j]=min(dist[j],dist[t]+g[t][j]); //更新1到j这条路的长度(从1到t,再从t到j的距离与1到j距离比较,换成短的那条路)}    

第二个循环:用当前找到的点t去更新后面的点到起点的距离,方法就是遍历1到n,每次看是1号点到j号点的距离大还是1号点到t号点,再从t号点到j号点的距离大,我们保留短的那条路。

    while(m--){int a,b,c;cin>>a>>b>>c;g[a][b]=min(g[a][b],c); //如果两个点之间有多条边,保留最短边,因为初始化g为无穷大,所以一开始是让g[a][b]=c,后面如果出现了一样的点,就会取其中的最小值}

在主函数中,因为题目没有说不存在自边和环,所以可能从一个点到另一个点有多条边,我们只需要保留其中最短的就好。

补充:这里的代码很多处都用到了0x3f,是因为这个数字能近似表达正无穷,它的值是1061109567,是10^9级别,并且还能保证无穷大加无穷大仍然不会超限,因为0x3f3f3f3f+0x3f3f3f3f=2122219134,这非常大但却没有超过32-bit int的表示范围,我们使用memset()是对char操作,即一个字节一个字节的操作,如果此时初始化的变量为int类型(4字节),那么此时的变量就会被初始化成四个0x3f,即0x3f3f3f3f(这个0x是十六进制的意思)。

  if(dist[n] == 0x3f3f3f3f)  //当1号点距离到n号点距离为无穷大时(即1和n不连通),注意这里变成了0x3f3f3f3f{return -1;}

在后面比较的时候,注意这个值是0x3f3f3f3f,我们只是用memset赋值的时候给每个字节赋值0x3f,整个int变量是0x3f3f3f3f。 

参考:0x3f~0x3f3f3f3f的来龙去脉(详解)-CSDN博客关于memset函数和赋值0x3f,2021-5-5-CSDN博客

示例代码:

#include<iostream>
#include<cstring>
#include<algorithm> using namespace std;
const int N=510;
int n,m;
int g[N][N];  //题目中是稠密图,用邻接矩阵写,g[1][2]表示从1节点指向2节点的距离
int dist[N];  //从1号点走到每个点的距离(最短距离)
bool st[N];  //每个点最短路是否已经确定,true为确定int dijkstra() 
{memset(dist,0x3f,sizeof(dist)); //初始化时每个点到起点距离为无穷大dist[1]=0;  //起点到自身的距离为0for(int i=0;i<n;i++) //迭代n次,每次做两件事:1.找到集合外到起点最短距离的点 2.用这个点来更新到其他点的最短距离{int t=0;  //t表示当前要找的集合外到起点最短距离的点,0表示初始化for(int j=1;j<=n;j++) //第一轮循环,寻找集合外到起点最短距离的点,一开始1号点也是在集合外的,所以j从1开始找{//找当前不确定最短距离的点集合外(即st为false)到起点距离最短的点if(!st[j] && (dist[t]>dist[j])) //当前点最短路还没被确定并且当前t不是最短的,一开始的d[t]是无穷,d[1]是0,所以1号点就会找到{t=j; //换成短的那条路 }}st[t]=true;  //找到了集合外到起点最短距离的点,标记(其实就是加入了确定最短距离的集合)for(int j=1;j<=n;j++) //第二轮循环,用已经确定了的最短距离的点来更新到其他点的最短距离{dist[j]=min(dist[j],dist[t]+g[t][j]); //更新1到j这条路的长度(从1到t,再从t到j的距离与1到j距离比较,换成短的那条路)}      }if(dist[n] == 0x3f3f3f3f)  //当1号点距离到n号点距离为无穷大时(即1和n不连通),注意这里变成了0x3f3f3f3f{return -1;}return dist[n];   //返回从1号点走到n号点的距离(最短距离)
}
int main()
{ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n>>m;  //读入点数和边数memset(g,0x3f,sizeof(g));  //0x3f是无穷大,memset按字节赋值,一个字节就是0x3f,int有四个字节,所以是0x3f3f3f3fwhile(m--){int a,b,c;cin>>a>>b>>c;g[a][b]=min(g[a][b],c); //如果两个点之间有多条边,保留最短边,因为初始化g为无穷大,所以一开始是让g[a][b]=c,后面如果出现了一样的点,就会取其中的最小值}cout<<dijkstra();return 0;
}

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

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

相关文章

使用JLink仿真器实现调试打印的N种方法

方法一&#xff1a;使用MCU的串口 这是最古老也是最简单的方法。 电脑上面插一个USB转TTL&#xff0c;然后与MCU的UART_RX/UART_TX/GND连接起来。PC端再打开一个串口调试助手。两边的波特率一致&#xff0c;就可以收到MCU发过来的打印信息了。 方法二&#xff1a;使用JLink仿…

低代码开发平台通常提供哪些功能?发挥什么作用?

目录 一、低代码助力开发 二、低代码核心功能 1.业务建模&#xff1a; 2.表单建模&#xff1a; 3.页面建模&#xff1a; 4.流程建模&#xff1a; 5.报表建模&#xff1a; 6.门户建模&#xff1a; 7.大屏建模&#xff1a; 8.移动建模&#xff1a; 三、解放程序员的双…

使用人工智能优化常见业务流程

在现代商业环境中&#xff0c;人工智能(AI)正在改变企业的运营方式。将人工智能集成到业务流程中可以提高效率和准确性&#xff0c;从而节省大量时间和成本。 这使员工能够专注于更具战略性的任务。人工智能在商业中的应用范围从自动化日常任务到提供高级分析&#xff0c;以做…

【实用】sklearn决策树怎么导出规则

目录 一、什么是决策树模型 0.1 什么是决策树 02.决策树模型有哪些 二、在sklearn中怎么训练一棵决策树 三、什么是决策树的规则 0.1决策树的决策规则 02. 决策树的决策规则是怎么存储的 四、怎么导出决策树的规则 4.1 导出决策树文本规则 4.2 导出可视化决策树 4.3…

MS1242,替代ADS1242,24bit 高精度、低功耗模数转换器

产品简述 MS1242/MS1243 是一款高精度、宽动态范围、 ∆-Σ 模数转 换芯片&#xff0c;其工作电压为 2.7V 至 5.25V &#xff0c;可以达到 24bit 无失码转 换&#xff0c;有效精度可达 21bit 。 MS1242/MS1243 可以广泛使用在工 业控制、称重、液体 / 气体化学分析、血液分…

利用Rclone将阿里云对象存储迁移至雨云对象存储的教程,对象存储数据迁移教程

使用Rclone将阿里云对象存储(OSS)的文件全部迁移至雨云对象存储(ROS)的教程&#xff0c;其他的对象存储也可以参照本教程。 Rclone简介 Rclone 是一个用于和同步云平台同步文件和目录命令行工具。采用 Go 语言开发。 它允许在文件系统和云存储服务之间或在多个云存储服务之间…

如何公网访问内网的群晖NAS随时随地远程访问本地存储的学习资源

文章目录 前言本教程解决的问题是&#xff1a;按照本教程方法操作后&#xff0c;达到的效果是前排提醒&#xff1a; 1. 搭建群晖虚拟机1.1 下载黑群晖文件vmvare虚拟机安装包1.2 安装VMware虚拟机&#xff1a;1.3 解压黑群晖虚拟机文件1.4 虚拟机初始化1.5 没有搜索到黑群晖的解…

伪原创API,一文快速了解伪原创API

伪原创API&#xff0c;听起来可能对许多人来说是一个陌生的术语。然而&#xff0c;在当今数字化时代&#xff0c;尤其是在内容创作和网络营销领域&#xff0c;伪原创API正逐渐崭露头角。在本文中&#xff0c;我将向您深入介绍伪原创API是什么&#xff0c;以及它如何在实际应用中…

Weblogic CVE-2023-21839(metasploit版)

Step1&#xff1a;用docker搭建环境 Step2&#xff1a;docker查看映射端口 Step3&#xff1a;访问特定端口&#xff0c;然后靶标应用。 Step4&#xff1a;用metasploit进行攻击&#xff1a; 首先&#xff0c;打开metasploit&#xff0c;然后查询需要攻击的板块&#xff0…

Python中的并发编程(3)线程池、锁

concurrent.futures 提供的线程池 concurrent.futures模块提供了线程池和进程池简化了多线程/进程操作。 线程池原理是用一个任务队列让多个线程从中获取任务执行&#xff0c;然后返回结果。 常见的用法是创建线程池&#xff0c;提交任务&#xff0c;等待完成并获取结果&…

内网穿透的应用-如何结合Cpolar内网穿透工具实现在IDEA中远程访问家里或者公司的数据库

文章目录 1. 本地连接测试2. Windows安装Cpolar3. 配置Mysql公网地址4. IDEA远程连接Mysql小结 5. 固定连接公网地址6. 固定地址连接测试 IDEA作为Java开发最主力的工具&#xff0c;在开发过程中需要经常用到数据库&#xff0c;如Mysql数据库&#xff0c;但是在IDEA中只能连接本…

SpringMVC项目出现404

目录 问题讲解&#xff1a; 解决方案&#xff1a; 1、处理器映射器和处理器适配器以及视图解析器没有配置好 2、Controller的包扫描没有加或者包扫描的配置是错误的 3、当然也有说jar包没有 4、请求地址是错误的 5、还有一种解决办法说web.xml配置DispatcherServlet的时…