初识最短路径

一.最短路径的介绍

最短路径是图论和网络分析中一个重要的概念,它指的是在一个图或网络中连接两个节点或顶点的路径中,具有最小权重总和的路径。这个权重可以表示为路径上边或弧的长度、耗费、时间等,具体取决于问题的背景和应用场景。

如果你有学过最小生成树,你会发现,二者是有部分相同点的,都是在找权重和的最小值。

但是最小生成树找的是沟通所有节点的最小权重,而最短路径是找的是一个节点到另一个节点的最小权重。

因为从一个节点到另一个节点往往有多种路径,路径的长短也不同,我们的目的就是为了找到一个最短的路径,来达到省时省力的目的。

比如我们从A节点到E节点,分别有三条路径。

上路径:2(A->B)+4(B->E)=6

中路径:10(A->E)

下路径:4(A->C)+2(C->D)+6(D->E)=12

那么我们怎么使用代码找出最短路径呢?

用于解决最短路径可以使用Dijkstra 算法、SPFA算法、Floyd 算法等。

下面我们对这几种算法来介绍一下。

二.算法介绍

这里先给出一个例题,使用下面介绍成所有算法解决。

例题

输入数据:

4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4

1.Dijkstra 算法

Dijkstra 算法基于贪心策略,通过逐步找到从起点到所有其他节点的最短路径来工作。它适用于权重为非负的有向图和无向图。

算法的实现有以下几个步骤:

1.distances:距离数组,用于存储从起点到每个节点的最短距离估计值。初始时,将起点到自身的距离设置为0,其他节点的距离设置为无穷大。

2.visited:标记数组,用于标记节点是否已经被访问过。初始时,将所有节点标记为未访问。

3.previous:前驱数组,用于记录到达每个节点的最短路径中,当前节点的前一个节点是哪个。

4.从起点开始,将起点标记为当前节点,更新起点到相邻节点的距离,并将这些相邻节点加入候选集。

5.从候选集中选择距离最短的节点作为当前节点,并将其标记为已访问。

6.对于当前节点的每个相邻节点,如果经过当前节点到达该相邻节点的路径比起始点直接到达该节点的路径更短,则更新距离数组和前驱数组。

7.重复步骤3和步骤4,直到所有节点都被访问过或候选集为空。

8.最终得到起点到每个节点的最短路径长度和最短路径。

下面是实现例题的完整代码(含注释):

#include<bits/stdc++.h>
#define M 500010
#define inf 1234567890
using namespace std;
struct edge{int u,v,w,next;
}e[M];
struct node{int w,now;bool operator<(const node &k)const{return w>k.w;//堆优化,小的元素放在堆顶,大根堆 }
};
int head[M],re=0,n,m,s,v[M],dis[M];
priority_queue<node>q;
void add(int u,int v,int w)//链式前向星存图 
{e[++re].u=u;e[re].v=v;e[re].w=w;e[re].next=head[u];head[u]=re;
}
void dijkstra()
{for(int i=1;i<=n;i++) dis[i]=inf;//将点设置为无穷大 dis[s]=0;//起点设置为0 node p;p.w=0,p.now=s;q.push(p);while(!q.empty()){node k=q.top();q.pop();int u=k.now;if(v[u]) continue;//如果遍历过,直接跳过循环 v[u]=1;for(int i=head[u];i;i=e[i].next){//下一个点 int v=e[i].v;if(dis[v]>dis[u]+e[i].w)//更新最小权重 {dis[v]=dis[u]+e[i].w;q.push((node){dis[v],v});}		}}
}
int main()
{cin>>n>>m>>s;for(int i=0;i<m;i++){int u,v,w;cin>>u>>v>>w;//建边 add(u,v,w);}dijkstra();for(int i=1;i<=n;i++){cout<<dis[i]<<" ";}return 0;
}

我们来看运行结果:

也是成功AC。

2.SPFA算法

SPFA算法是一种用于解决单源最短路径问题的算法,是 Bellman-Ford 算法的一种优化版本。它通过队列实现松弛操作,以减少不必要的松弛次数,从而提高了算法的效率。

算法实现步骤:
1.distances:距离数组,用于存储从起点到每个节点的最短距离估计值。初始时,将起点到自身的距离设置为0,其他节点的距离设置为无穷大。

2.queue:队列,用于存储待处理的节点。初始时,将起点加入队列。

3.in_queue:标记数组,用于标记节点是否已经在队列中。初始时,将起点标记为在队列中。

4.从队列中取出一个节点作为当前节点,遍历该节点的所有相邻节点。

5.对于每个相邻节点,如果经过当前节点到达该相邻节点的路径比起始点直接到达该节点的路径更短,则更新距离数组,并将该相邻节点加入队列。

6.重复直到队列为空。

下面是实现例题的完整代码:

#include<bits/stdc++.h>
#define M 500010
#define inf 1234567890
using namespace std;
struct edge{int u,v,w,next;
}e[M];
int head[M],re=0,n,m,s,v[M],dis[M];
void add(int u,int v,int w)//链式前向星存图 
{e[++re].u=u;e[re].v=v;e[re].w=w;e[re].next=head[u];head[u]=re;
}
queue<int>q;//队列优化 
void SPFA()
{for(int i=1;i<=n;i++) dis[i]=inf;//将点设置为无穷大 dis[s]=0;//起点设置为0 q.push(s);while(!q.empty()){//直到所有节点全部入队,不会再有新的节点入队,慢慢出队至停止循环 int k=q.front();q.pop();v[k]=0;for(int i=head[k];i;i=e[i].next){//下一个点 int p=e[i].v;if(dis[p]>dis[k]+e[i].w)//更新最小权重 {dis[p]=dis[k]+e[i].w;if(!v[p])//如果不在队列里面,则入队 {v[p]=1;q.push(p);}}		}}
}
int main()
{cin>>n>>m>>s;for(int i=0;i<m;i++){int u,v,w;cin>>u>>v>>w;//建边 add(u,v,w);}SPFA();for(int i=1;i<=n;i++){cout<<dis[i]<<" ";}return 0;
}

下面是运行结果:

虽然运行结果正确,但是SPFA算法容易被卡数据,导致时间超限。

3.Floyd 算法

Floyd算法的时间复杂度为O(N^3),其中N是节点的数量。因此,对于大型图,Floyd算法可能会变得相对缓慢。然而,与其他单源最短路径算法不同,Floyd算法可以同时计算任意两个节点之间的最短路径,这在某些情况下可能是更方便的。

Floyd算法的核心是下面这个方程式,来自动态规划。

dp[j][k]=min(dp[j][k],dp[j][i]+dp[i][k]);

算法实现步骤:

  1. 初始化距离矩阵:将矩阵D初始化为图的邻接矩阵,如果两个节点之间有直接的边,则距离为边的权重;否则,距离为无穷大。同时,将对角线上的元素(即节点到自身的距离)初始化为0。

  2. 三重循环:对于每一对节点(i,j)作为可能的中间节点k,检查是否存在路径从节点i到节点j通过节点k的路径比直接从i到j的路径更短。如果是,则更新路径长度。

  3. 返回最终的距离矩阵D,其中D[i][j]表示从节点i到节点j的最短路径长度。

Floyd算法是这三种算法中最简单的,核心代码只有一点。

for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(i==j||dp[j][i]==inf) continue;for(int k=1;k<=n;k++){dp[j][k]=min(dp[j][k],dp[j][i]+dp[i][k]);} }}

下面是完整代码:

#include<bits/stdc++.h>
using namespace std;
#define M 10010
#define inf 1234567890
int n,m,s,dp[M][M];
void floyd()
{for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(i==j||dp[j][i]==inf) continue;//找存在边 for(int k=1;k<=n;k++){dp[j][k]=min(dp[j][k],dp[j][i]+dp[i][k]);//更新最小权重 } }}
}
int main()
{cin>>n>>m>>s;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)dp[i][j]=inf;//初始化矩阵 for(int i=1;i<=m;i++){int u,v,w;cin>>u>>v>>w;dp[u][v]=min(dp[u][v],w);//防止重边 }dp[s][s]=0;floyd();for(int i=1;i<=n;i++){cout<<dp[s][i]<<" ";}return 0;
}

下面是运行结果:

结果虽然正确,但是对于这题来说,运行速度太慢了。

所以在做题时,需要按照题目要求来选择合适算法。

三.总结

  1. Dijkstra算法:

    • 简介: Dijkstra算法是解决单源最短路径问题的一种贪心算法。它从起点开始,逐步找到从起点到所有其他节点的最短路径。
    • 运行速度: 在最坏情况下,Dijkstra算法的时间复杂度为O((V+E)logV),其中V是节点数,E是边数。在使用最小堆的实现中,它通常具有较好的性能。
  2. SPFA算法:

    • 简介: SPFA算法是Bellman-Ford算法的一种优化版本,通过使用队列来避免不必要的重复松弛操作,提高了效率。
    • 运行速度: SPFA算法的平均时间复杂度通常被认为是O(kE),其中k是一个常数。在实际应用中,它的性能通常比Bellman-Ford算法好,但对于存在负权回路的图,SPFA算法可能陷入死循环。
  3. Floyd算法:

    • 简介: Floyd算法是一种动态规划算法,用于解决图中所有节点对之间的最短路径问题。它通过迭代更新每一对节点之间的最短路径长度。
    • 运行速度: Floyd算法的时间复杂度为O(N^3),其中N是节点的数量。在大型图上可能变得相对缓慢,但与其他单源最短路径算法不同,Floyd算法可以同时计算任意两个节点之间的最短路径。

速度比较:

  • Dijkstra算法通常在稠密图上表现良好,特别是当使用最小堆等数据结构进行优化时。
  • Floyd算法的运行速度可能在大型图上较慢,但由于同时计算所有节点对之间的最短路径,它在某些情况下可能更方便。

总体而言,选择算法通常取决于图的规模、稀密度、边权重分布以及是否需要同时计算所有节点对之间的最短路径。


本篇完~

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

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

相关文章

【STM32 CubeMX】SPI层次结构SPI协议与SPI控制器结构

文章目录 前言一、SPI 程序层次1.1 硬件原理图1.2 硬件框图1.3 软件层次 二、SPI协议2.1 硬件连线2.2 如何访问SPI设备2.3 SPI 框图 总结 前言 随着嵌入式系统的迅猛发展&#xff0c;STM32系列微控制器在各种应用中得到广泛应用。在嵌入式系统设计中&#xff0c;串行外设接口&…

Anaconda、conda、pip、virtualenv的区别

① Anaconda Anaconda是一个包含180的科学包及其依赖项的发行版本。其包含的科学包包括&#xff1a;conda, numpy, scipy, ipython notebook等。 Anaconda具有如下特点&#xff1a; ▪ 开源 ▪ 安装过程简单 ▪ 高性能使用Python和R语言 ▪ 免费的社区支持 其特点的实现…

牛客网SQL进阶123:高难度试卷的得分的截断平均值

官网链接&#xff1a; SQL类别高难度试卷得分的截断平均值_牛客题霸_牛客网牛客的运营同学想要查看大家在SQL类别中高难度试卷的得分情况。 请你帮她从exam_。题目来自【牛客题霸】https://www.nowcoder.com/practice/a690f76a718242fd80757115d305be45?tpId240&tqId2180…

matplotlib从起点出发(13)_Tutorial_13_Autoscaling

0 自动放缩 轴上的限制可以手动设置&#xff08;例如ax.set_xlim(xmin, xmax))&#xff0c;或者Matplotlib可以根据Axes上已有的数据自动设置它们。此种放缩行为有许多选项&#xff0c;如下所述。 我们将从一个简单的折线图开始&#xff0c;显示自动缩放将轴限制扩展到数据的…

08MARL深度强化学习——模型种类

文章目录 前言1、训练与执行的模型2、Centralised Training and Execution2.1 Example——central learning2.2 局限性 3、Decentralised Training and Execution3.1 Example——independent learning3.2局限性 4、Centralised Training with Decentralised Execution4.1 Examp…

vue实现多个下拉框联动(二)

在Vue3的组件中&#xff0c;定义多个下拉框的数据和选中的值。例如&#xff1a; data() {return {firstSelectValue: ,secondSelectValue: ,thirdSelectValue: ,// 其他下拉框的数据和选中的值} }在模板中&#xff0c;使用v-model指令绑定下拉框的选中值&#xff0c;并使用cha…

精读《Function Component 入门》

1. 引言 如果你在使用 React 16&#xff0c;可以尝试 Function Component 风格&#xff0c;享受更大的灵活性。但在尝试之前&#xff0c;最好先阅读本文&#xff0c;对 Function Component 的思维模式有一个初步认识&#xff0c;防止因思维模式不同步造成的困扰。 2. 精读 什…

P1090 [NOIP2004 提高组] 合并果子 / [USACO06NOV] Fence Repair G题解

题目 在一个果园里&#xff0c;多多已经将所有的果子打了下来&#xff0c;而且按果子的不同种类分成了不同的堆。多多决定把所有的果子合成一堆。 每一次合并&#xff0c;多多可以把两堆果子合并到一起&#xff0c;消耗的体力等于两堆果子的重量之和。可以看出&#xff0c;所…

如何将浏览器设置为黑色

步骤 1 设置边框颜色&#xff1a; 找到浏览器的 设置 选项在里面选择浏览器的 外观 选项把 主题 相关的改成 黑色 即可 步骤 2 设置页面背景颜色&#xff1a; 在浏览器搜索栏中输入指令&#xff0c;并确认 浏览器类型指令edgeedge://flags/chromechrome://flags/ 在出现…

绿色化 数据库 MongoDB 和 mysql 安装

绿色化 数据库 MongoDB 和 mysql 安装 【1.1】 前言 为什么要绿色化 安装呢&#xff1f;因为系统老升级&#xff0c;老重装&#xff01;&#xff01;也方便了解下数据库配置和库在那 绿色软件喜欢一般放在 D盘tools目录里 D:\tools\ 数据库 MongoDB D:\tools\MongoDB 数…

Mysql第二关之存储引擎

简介 所有关于Mysql数据库优化的介绍仿佛都有存储引擎的身影。本文介绍Mysql常用的有MyISAM存储引擎和Innodb存储引擎&#xff0c;还有常见的索引。 Mysql有两种常见的存储引擎&#xff0c;MyISAM和Innodb&#xff0c;它们各有优劣&#xff0c;经过多次优化和迭代&#xff0c;…

代码随想录算法训练营第十九天|654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树

654.最大二叉树 刷题https://leetcode.cn/problems/maximum-binary-tree/description/文章讲解https://programmercarl.com/0654.%E6%9C%80%E5%A4%A7%E4%BA%8C%E5%8F%89%E6%A0%91.html视频讲解https://www.bilibili.com/video/BV1MG411G7ox/?vd_sourceaf4853e80f89e28094a5fe…

洛谷题解 - B2015 计算并联电阻的阻值

目录 题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 代码 题目描述 对于阻值为 r 1 r_1 r1​ 和 r 2 r_2 r2​ 的电阻&#xff0c;其并联电阻阻值公式计算如下&#xff1a; R 1 1 r 1 1 r 2 R\dfrac{1}{\dfrac{1}{r_1}\dfrac{1}{r_2}} Rr1​1​r2​1​1​ 输入…

软件工程师,OpenAI Sora驾到,快来围观

概述 近期&#xff0c;OpenAI在其官方网站上公布了Sora文生视频模型的详细信息&#xff0c;展示了其令人印象深刻的能力&#xff0c;包括根据文本输入快速生成长达一分钟的高清视频。Sora的强大之处在于其能够根据文本描述&#xff0c;生成长达60秒的视频&#xff0c;其中包含&…

【Spring1】Spring容器的本质就是两个HashMap

做为Java程序员,我们就是Spring的用户,Spring的影子在我们的代码里几乎是无处不在,那Spring到底是什么,带给我们什么,如何工作的呢?这个简单问题貌似又不太好讲。例如如果要问一下什么是Spring框架, 可以找到大量的解答,基本内容如下: Spring是一个开源的应用程序框架…

计算机网络-OSI模型及网络数据传输(双十一淘宝故事详解版)

首先&#xff0c;把一个资源的传输&#xff0c;想象成在双十一下&#xff0c;商品琳琅满目&#xff0c;然后剁手党们经不住诱惑&#xff0c;疯狂买买买。在OSI中资源传输就相当于淘宝 卖家发货--->买家收货的过程。 其中每一层分别如下所示&#xff1a; 应用层&#xff08…

开源无处不在,发展创新下又有何弊端

随着信息技术的快速发展&#xff0c;开源软件已经成为软件开发的趋势&#xff0c;并产生了深远的影响。开源软件的低成本、可协作性和透明度等特点&#xff0c;使得越来越多的企业和个人选择使用开源软件&#xff0c;促进了软件行业的繁荣。然而&#xff0c;在使用开源软件的过…

1、若依(前后端分离)框架的使用

若依&#xff08;前后端分离&#xff09;框架的使用 0、环境1、下载若依(1) 下载并解压(2) 导入SQL语句(3) 配置Redis、MySQL 2、运行若依3、登录(1) 前端(2) 后端 4、获取用户角色、权限和动态路由(1) 获取用户角色、权限(2) 根据用户信息获取动态路由【getRouters】 5、杂6、…

python37-Python列表和元组之长度、最大值和最小值

Python提供了内置的len()max()min()全局函数来获取元组或列表的长度、最大值和最小值。 由于max()、min()要对元组、列表中的元素比较大小,因此程序要求传给max(),min()函数的元组、列表的元素必须是相同类型且可以比较大小。例如如下代码: # !/usr/bin/env python# -*- cod…

阿里云服务器ECS租赁费用报价_CPU内存_带宽和系统盘价格表

2024年最新阿里云服务器租用费用优惠价格表&#xff0c;轻量2核2G3M带宽轻量服务器一年61元&#xff0c;折合5元1个月&#xff0c;新老用户同享99元一年服务器&#xff0c;2核4G5M服务器ECS优惠价199元一年&#xff0c;2核4G4M轻量服务器165元一年&#xff0c;2核4G服务器30元3…