Dijkstra求最短路 I(Dijkstra算法)

news2024/12/25 23:50:40

给定一个 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;  //起点到自身的距离为0
    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距离比较,换成短的那条路)
        }      
    }
    
    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有四个字节,所以是0x3f3f3f3f
    while(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.coloradmin.cn/o/1302152.html

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

相关文章

HubSpot细分目标市场:拓展业务边界,突破增长瓶颈

在数字化时代&#xff0c;企业面临前所未有的市场挑战。随着科技的飞速发展&#xff0c;消费者期望个性化的体验&#xff0c;即时的互动&#xff0c;以及高质量、有价值的信息。这些变化使得企业不仅需要适应新的技术和趋势&#xff0c;还需要更加精细化地理解和满足不同细分市…

新工具:CloudBees Pipeline Explorer改善日志查看体验,简化复杂Jenkins流水线故障排除

流水线是开发过程的关键组成部分&#xff0c;然而&#xff0c;在复杂的流水线中进行故障排除是一件耗时且繁琐的事情&#xff0c;特别是对于规模较大的公司而言。 这就是CloudBees Pipeline Explorer用武之处&#xff0c;它提供了一种简化且高效的流水线故障排除方法。 现有流…

win10脚本 | 使用 Word 自动化对象模型找出指定路径下含有特定内容的.docx

场景 今年的实验日志被我放在这样一个文件夹下&#xff0c;每个月下是每天具体的.docx文件&#xff0c;里面记录了我的一些实验操作步骤。现在我需要补充一个实验&#xff0c;用到一个名为chatunitest的插件&#xff0c;但是这是很久之前做的事情了&#xff0c;我无法判断是哪…

chronyc立即加载时间同步

不需要等待直接加载 chronyc makestep chronyc sources -v chronyd 服务正在使用的 NTP 源服务器的详细状态。这个命令会列出每个源服务器的 IP 地址&#xff0c;以及每个源服务器的状态和时间偏移量。通过这个命令&#xff0c;你可以看到你的系统是从哪些 NTP 服务器获取时间…

边缘智能网关如何应对环境污染难题

随着我国工业化、城镇化的深入推进&#xff0c;包括大气污染在内的环境污染防治压力继续加大。为应对环境污染防治难题&#xff0c;佰马综合边缘计算、物联网、智能感知等技术&#xff0c;基于边缘智能网关打造环境污染实时监测、预警及智能干预方案&#xff0c;可应用于大气保…

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

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

程序员考公笔记之逻辑判断(图形推理)

文章目录 写在前面1、逻辑判断1.1、图形推理1.1.1、位置类1.1.2、样式类1.1.3、数量类1.1.4、属性类1.1.5、六面体 写在前面 1、逻辑判断 1.1、图形推理 观察&#xff1a;先宏观&#xff0c;再微观 图形推理的命题形式&#xff1a; 一组式 观察路径&#xff1a;顺序看(考最…

解密防泄密成功密码:银行机构案例分享迅软DSE带你走过风险之路!

近日&#xff0c;央行发布了《中国人民银行业务领域数据安全管理办法&#xff08;征求意见稿&#xff09;》&#xff0c;旨在落实《数据安全法》有关要求&#xff0c;加强中国人民银行业务领域数据安全管理。 从银行业务领域来看&#xff0c;数据主要涉及各类市场交易数据、金…

MeterSphere实战(一)

MeterSphere是一位朋友讲到的测试平台&#xff0c;说这东西是开源的&#xff0c;因为我是做测试的&#xff0c;很乐意了解一些新鲜事物。在我看来&#xff0c;测试就是要专注一些领域&#xff0c;然后要啥都会一点点&#xff0c;接着融会贯通起来&#xff0c;这样就可以万变不离…

自定义类型详解(1)

文章目录 目录1. 结构体1.1 结构的基础知识1.2 结构的声明1.3 特殊的声明1.4 结构的自引用1.5 结构体变量的定义和初始化1.6 结构体内存对齐1.7 修改默认对齐数1.8 结构体传参 2. 位段2.1 什么是位段2.2 位段的内存分配2.3 位段的跨平台问题2.4 位段的应用 3. 枚举3.1 枚举类型…

vue2-elementUI部分组件样式修改

el-radio样式&#xff1a; /deep/ .el-radio__input .el-radio__inner {width: 20px;height: 20px;position: relative;cursor: pointer;-webkit-appearance: none;-moz-appearance: none;appearance: none;border: 1px solid #999;border-radius: 0;outline: none;transition…

亚马逊鲲鹏系统智能自动注册与AI角色养号,探索数字化新境界

在数字化时代&#xff0c;亚马逊鲲鹏系统以其强大的自动化功能&#xff0c;为用户提供了前所未有的购物体验。如果你想利用鲲鹏系统进行自动化注册&#xff0c;那么准备好邮箱、IP、手机号等关键信息后&#xff0c;你将轻松实现自动注册&#xff0c;为购物之旅开启智能化新篇章…

V2X全方位通信部署产品支持智能交通建设!

来源&#xff1a;德思特测试测量丨德思特案例 | V2X全方位通信部署产品支持智能交通建设&#xff01; 原文链接&#xff1a;https://mp.weixin.qq.com/s/Fhnvcq9HA60Sed5BIGcnSw 欢迎关注虹科&#xff0c;为您提供最新资讯&#xff01; 01 案例背景 后疫情时代人们更注重于享…

CommonJs模块化实现原理ES Module模块化原理

CommonJs模块化实现原理 首先看一个案例 初始化项目 npm init npm i webpack -D目录结构如下&#xff1a; webpack.config.js const path require("path"); module.exports {mode: "development",entry: "./src/index.js",output: {path: p…

项目经理和产品经理哪个更有发展前景?

如果是单看“钱途”的话&#xff0c;如果是在传统行业&#xff0c;可能差不多&#xff1b;如果是在IT行业的话&#xff0c;可能更需要项目经理&#xff1b;互联网行业的话&#xff0c;可能更需要产品经理。 项目经理跟产品经理两个证都挺受市场欢迎的&#xff0c;两个岗位职责…

关于粒子群算法的一些简单尝试

粒子群算法核心思想&#xff1a;&#xff08;鸟 粒子&#xff09; &#xff08;1&#xff09;许多的鸟站在不同的地方&#xff1b; &#xff08;2&#xff09;每一只鸟都有自己寻找食物的初始飞行方向、飞行速度&#xff1b; &#xff08;3&#xff09;这些鸟儿每隔一段时间…

高级网工在Linux服务器抓包,少不了这几条常用的tcpdump命令。

Linux 的命令太多&#xff0c;tcpdump 是一个非常强大的抓包命令。有时候想看线上发生的一些问题&#xff1a; nginx 有没有客户端连接过来…… 客户端连接过来的时候 Post 上来的数据对不对…… 我的 Redis 实例到底是哪些业务在使用…… tcpdump 作为网络分析神器就派上用场…

湖农大邀请赛shell_rce漏洞复现

湖农大邀请赛 shell_rce 复现 在 2023 年湖南农业大学邀请赛的线上初赛中&#xff0c;有一道 shell_rce 题&#xff0c;本文将复现该题。 题目内容&#xff0c;打开即是代码&#xff1a; <?phpclass shell{public $exp;public function __destruct(){$str preg_replace…

2、快速搞定Kafka术语

快速搞定Kafka术语 Kafka 服务端3层消息架构 Kafka 客户端Broker 如何持久化数据小结 Kafka 服务端 3层消息架构 第 1 层是主题层&#xff0c;每个主题可以配置 M 个分区&#xff0c;而每个分区又可以配置 N 个副本。第 2 层是分区层&#xff0c;每个分区的 N 个副本中只能有…

Java集合进阶

目录 集合体系结构 Collection集合 List集合 ArrayList集合 LinkedList集合 集合体系结构 注意:有序:存进去的数组和取出来时一样 而不是大小的那种有序 Collection集合 单列集合顶层接口Collection import java.util.ArrayList; import java.util.Collection;public cl…