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]是最大的(正无穷),多次比较之后,dist值最小的点就会加入集合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.mzph.cn/news/224143.shtml

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

相关文章

python和pygame实现捉小兔游戏

python和pygame实现捉小兔游戏 python和pygame实现捉小兔游戏&#xff0c;需要安装使用第三方库pygame&#xff0c;关于Python中pygame游戏模块的安装使用可见 https://blog.csdn.net/cnds123/article/details/119514520 下面是使用Python和Pygame创建的游戏&#xff0c;其中有…

Pytorch从零开始实战13

Pytorch从零开始实战——ResNet与DenseNet探索 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——ResNet与DenseNet探索环境准备数据集模型选择开始训练可视化总结 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#xff0c;P…

Java连接数据库实现用户登录和注册功能

目录 需求内容如下 示例代码 数据库studb Java代码 效果图 需求内容如下 1&#xff0c;创建数据库studb 2&#xff0c;库中添加用户表userinfo,包含如下字段 用户id ,用户名&#xff0c;用户密码&#xff0c;用户权限 &#xff08;数据类型和约束自己定义&#xff09…

web微服务规划

一、背景 通过微服务来搭建web系统&#xff0c;就要对微服务进行规划&#xff0c;包括服务的划分&#xff0c;每个服务和数据库的命名规则&#xff0c;服务用到的端口等。 二、微服务划分 1、根据业务进行拆分 如&#xff1a; 一个购物系统可以将微服务拆分为基础中心、会员…

SpringMVC异常处理机制

2.1 异常描述 在J2EE项目的开发中&#xff0c;不管是对底层的数据库操作过程&#xff0c;还是业务层的处理过程&#xff0c;还是控制层的处理过程&#xff0c;都不可避免会遇到各种可预知的、不可预知的异常需要处理。每个过程都单独处理异常&#xff0c;系统的代码耦合度高&a…

【C++入门到精通】 线程库 | thread类 C++11 [ C++入门 ]

阅读导航 引言一、thread类的简单介绍二、线程函数详细介绍1. start() 函数&#xff08;1&#xff09;头文件&#xff08;2&#xff09;函数原型 2. join() 函数&#xff08;1&#xff09;头文件&#xff08;2&#xff09;函数原型 3. detach() 函数&#xff08;1&#xff09;头…

LeetCode Hot100 25.K个一组翻转链表

题目&#xff1a; 给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯…

7+m6A+分型+实验,甲基化方向的生信思路,没有思路的同学可参考

今天给同学们分享一篇生信文章“Landscape analysis of m6A modification regulators related biological functions and immune characteristics in myasthenia gravis”&#xff0c;这篇文章发表在J Transl Med期刊上&#xff0c;影响因子为7.4。 结果解读&#xff1a; MG相…

快速文件搜索软件 Everything-voidtools

Everything 文件搜索软件 "Everything"是一款快速、轻巧且高效的桌面搜索引擎软件&#xff0c;专门用于在 Windows 操作系统上搜索文件和文件夹。它的主要特点是超快的搜索速度和精准的搜索结果&#xff0c;能够让用户快速找到他们需要的文件或文件夹。 1. 快速搜…

IDEA小技巧

目录 1. IDEA自动添加注释 创建类的时候自动添加注释 创建函数、方法的注释 1. IDEA自动添加注释 参考文档&#xff1a;idea java 自动添加文件注释 idea新建类自动注释_mob6454cc73c728的技术博客_51CTO博客 【操作工具】IDEA创建类及已有类添加注释-详细操作_idea设置创建…

搭建个人智能家居 开篇(搭建Home Assistant)

搭建个人智能家居 开篇&#xff08;搭建Home Assistant&#xff09; 前言Home Assistant搭建Home AssistantUbuntu系统搭建Windows系统搭建VM安装方法VirtualBox安装方法&#xff1a; 配置Home Assistant控制页面 前言 随着科技的进步、发展&#xff0c;物联网给我们的生活带来…

JdbcTemplate query系列方法指定jdbcType类型

使用SqlParameterValue类包装一下就行了&#xff0c;只要创建一个SqlParameterValue对象&#xff0c;通过构造函数把jdbcType类型&#xff08;用的是Types中的常量&#xff09;和值传入 例如&#xff1a; // 这两个包下面的 import org.springframework.jdbc.core.SqlParamete…

c YUV 转 JPEG(准备霍夫曼编码)

先取yuv 文件中一个168的块&#xff0c;跑通全流程 理解与思路&#xff1a; 1.块分割 YUV 文件分为&#xff1a;YUV444 YUV 422 YUV420。444:就是&#xff1a;12个char 有4个Y&#xff0c;4个U&#xff0c;4个 U&#xff0c;422&#xff1a;8个char 中有4个Y &#x…

Redis——01,服务器购买、安装Redis

服务器购买、安装Redis 一、随便去一个主流的国内主流的云服务提供商&#xff0c;购买一个服务器。二、Redis安装&#xff1a;————————创作不易&#xff0c;如觉不错&#xff0c;随手点赞&#xff0c;关注&#xff0c;收藏(*&#xffe3;︶&#xffe3;)&#xff0c;谢…

[论文阅读]Multimodal Virtual Point 3D Detection

Multimodal Virtual Point 3D Detection 多模态虚拟点3D检测 论文网址&#xff1a;MVP 论文代码&#xff1a;MVP 论文简读 方法MVP方法的核心思想是将RGB图像中的2D检测结果转换为虚拟的3D点&#xff0c;并将这些虚拟点与原始的Lidar点云合并。具体步骤如下&#xff1a; (1)…

VINS-MONO代码解读6----pose_graph

开始pose_graph部分&#xff0c;本部分记住一句话无论是快速重定位还是正常重定位&#xff0c;求出 T w 1 w 2 T_{w_1w_2} Tw1​w2​​就是终极目标。 还剩一个整体Pipeline~~ 1. pose_graph_node.cpp 注意&#xff0c;定义全局变量时即实例化了一个对象 PoseGraph posegra…

C++之模板

目录 泛型编程 模板 函数模板 函数模板的实例化 隐式实例化 显示实例化 类模板 我们知道STL&#xff08;标准模板库&#xff09;是C学习的精华所在&#xff0c;在学习STL之前我们得先学习一个新的知识点-------模板。那么模板究竟是什么呢&#xff1f;围绕着这个问题&a…

绘图示例---QT手动调用绘图事件,按钮控制图片

效果&#xff1a; 点击 “移动” 图片向右移动20&#xff0c;点击 “西理win嘛” 图片每秒向右移动20 QQ录屏20231212164128 下面时代码详解&#xff1a; 注意使用UI和代码实现按钮的不同 UI: ui->pushButton->setGeometry(windowWidth-105, windowHeight-25, 100, 20);…

【思考】只有实对称矩阵才能正交对角化吗?【矩阵的合同】

1&#xff1a;命题改写&#xff08;A可以正交对角化&#xff09; 2&#xff1a;左乘Q右乘Q逆&#xff08;Q转置&#xff09; 3&#xff1a;取转置 4&#xff1a;得证 总结 可以看到&#xff0c;矩阵如果可以正交对角化&#xff0c;那么一定是实对称矩阵。 另外&#xff0c;这…

【期末复习向】长江后浪推前浪之ChatGPT概述

参考文章&#xff1a;GPT系列模型技术路径演进-CSDN博客 这篇文章讲了之前称霸NLP领域的预训练模型bert&#xff0c;它是基于预训练理念&#xff0c;采用完形填空和下一句预测任务2个预训练任务完成特征的提取。当时很多的特定领域的NLP任务&#xff08;如情感分类&#xff0c…