当前位置: 首页 > news >正文

图的最短路径

最短路径算法对图结构没有特殊要求,不要求连通图,且有向图无向图均可。

最短路径算法目标是求得从某顶点出发,沿图的边到达另一顶点所经过的路径中,各边上权值之和最小的一条路径。解决最短路的问题有以下算法:Dijkstra算法,Floyd算法和SPFA算法等。其中SPFA算法可以处理边权值为负数图结构。而最为好用的是使用堆优化的Dijstra算法。

(一)Dijkstra算法

算法采用动态规划的思想,通过对图结构的递推,得到从点X出发,到其他所有结点的最短路径(不能处理边权为负值情况)。以下图为例,求结点1出发,到其余各结点最短路径。

(1)先找到从1出发的邻接点有(2,3,4),最短的边是(1,3,长度5),此时可以断言结点1到结点3最短路径是5。证明也很容易,因为其他路径必须先经过(1,2,长度10)或者(1,4,长度9)那么其长度必然大于5。

(2)从3出发找寻到其他结点更短的路径,可以发现

5+(3,2,长度2)要比原来的(1,2,长度10)更小,进行数据的更新;

5+(3,5,长度6)就不如原有的(1,4,长度9),不作更新操作;

5+(3,5,长度1)要比原来的(1,5,长度无穷大)更小,进行数据的更新。

更新全部之后选出最小的路径,此时为(1,3,2)长度7,此路径为结点1到结点2的最短路径。然后从结点2出发继续找寻到其他结点更短的路径。

算法实现细节:(1)用v数组标记已经求出最短路径的结点;(2)用d数组记录最短路径长度,通过迭代方式更新d数组,找到当前最短路径结点。

邻接表存储的算法实现。

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int n,m,v[105],d[105];
struct node
{int adj,val;
};
vector<node>e[105];
int getMin()
{int mini=0,i;for(i=1;i<=n;i++)if(v[i]==0&&d[i]<d[mini])mini=i;return mini;
}
void djstra(int s)
{int i,j;memset(d,127/3,sizeof(d));/**< 初始化d数组 */d[s]=0;/**< s为起点 */for(i=1; i<=n; i++){int temp=getMin();v[temp]=1;for(j=0; j<e[temp].size(); j++) /**< e[1] 存的是2 4 5,e[1][j] */{int x=e[temp][j].adj,z=e[temp][j].val;if(v[x]==0&&d[x]>d[temp]+z)d[x]=d[temp]+z;}}
}
int main()
{ios::sync_with_stdio(0),cin.tie(0);int i,j,x,y,z,ans=0;cin>>n>>m;for(i=1; i<=m; i++){cin>>x>>y>>z;e[x].push_back({y,z});e[y].push_back({x,z});}djstra(1);if(d[n]<1e8)cout<<d[n];elsecout<<-1;return 0;
}

邻接表用堆优化的算法

#include <iostream>
#include<cstring>
#include <queue>
#include<vector>
typedef long long ll;
using namespace std;
int n,m,v[105],d[105];
struct node
{int adj,val;bool operator<(const node B)const/**< 重载操作符,用于优先队列排序 */{return val>B.val;}
};
vector<node>e[105];
priority_queue<node>pq;
int getMin()/**< 用堆之后查找复杂度降为log级别 */
{while(pq.size()&&v[pq.top().adj])/**< 存在堆顶元素已经访问的情况 */pq.pop();int v=pq.top().adj;pq.pop();return v;
}
void djstra(int s)
{int i,j;memset(d,127/3,sizeof(d));/**< 初始化d数组 */d[s]=0;/**< s为起点 */for(i=1; i<=n; i++)/**< 初始化优先队列,放入结点i和对应的d[i],这里只是借用node类型,这两个值可不是邻接点和权值(正常来说需要再定义一个结构体类型) */pq.push({i,d[i]});for(i=1; i<=n; i++){int temp=getMin();v[temp]=1;for(j=0; j<e[temp].size(); j++) /**< e[1] 存的是2 4 5,e[1][j] */{int x=e[temp][j].adj,z=e[temp][j].val;if(v[x]==0&&d[x]>d[temp]+z)d[x]=d[temp]+z,pq.push({x,d[x]});}}
}
int main()
{ios::sync_with_stdio(0),cin.tie(0);int i,j,x,y,z,ans=0;cin>>n>>m;for(i=1; i<=m; i++){cin>>x>>y>>z;e[x].push_back({y,z});e[y].push_back({x,z});}djstra(1);if(d[n]<1e8)cout<<d[n];elsecout<<-1;return 0;
}

(二)Floyd算法

必须使用邻接矩阵存储结构。基于动态规划思想,通过n个点的拉伸得到任意两点最短路径。检查每一个结点k,试探能否通过k为中间结点减少结点i和j的最短路径长度。Floyd算法时间复杂度较高O(n3),但是能用于求任意两点最短路径。算法简单,只适用于结点数较少的情况。

#include <iostream>
#include <cstring>
typedef long long ll;
using namespace std;
int n,m,a[105][105];
int main()
{ios::sync_with_stdio(0),cin.tie(0);int i,j,k,x,y,z;cin>>n>>m;memset(a,127/3,sizeof(a));for(i=1;i<=m;i++){cin>>x>>y>>z;/**< 必须无向图 */a[x][y]=a[y][x]=z;}for(k=1;k<=n;k++){for(i=1;i<=n;i++){for(j=1;j<=n;j++){if(a[i][j]>a[i][k]+a[k][j])/**< 检查以k为中间点,是否能减少i和j的路径长度 */a[i][j]=a[i][k]+a[k][j];}}}if(a[1][n]>9999999)cout<<-1;elsecout<<a[1][n];return 0;
}

(三)SPFA算法

SPFA算法写起来和BFS算法几乎一模一样,也被称为队列优化算法,通常用于求含负权边的单源最短路径,以及判负权环。其处理过程和迪杰斯特拉区别在于,迪杰斯特拉算法需要找到最小的那个结点,而SPFA不管那些,只要一个结点的当前路径长度低于之前已有的值,那么就送入队列,因为新的路径长度可能刷新其他结点的最短路径长度。

#include <iostream>
#include <string.h>
#include<vector>
#include<queue>
typedef long long ll;
using namespace std;
int n,m,v[100005],d[100005];/**< V表示结点是否在队列中 */
vector< pair<int,int> > e[100005];
void spfa(int x)
{int i,temp;d[x]=0;queue<int>q;q.push(x);/**< 起点入队 */while(!q.empty()){temp=q.front();/**< temp出队结点,如果一个结点会反复入队出队超过n次,那么有负环存在 */q.pop();v[temp]=0;/**< 修改标志,未来可能会再次入队 */for(i=0;i<e[temp].size();i++){int y=e[temp][i].first,z=e[temp][i].second;if(d[y]>d[temp]+z) /**< y结点的路径长度变短 */{d[y]=d[temp]+z;if(v[y]==0)/**< 如果y结点此时不在队列中,加入队列中 */{q.push(y);v[y]=1;/**< 标记一下,假如在y出来之前又一次d[y]>d[temp]+z,那么也不用重复入队 */}}}}
}
int main()
{ios::sync_with_stdio(0),cin.tie(0);int i,j,x,y,z,s;cin>>n>>m;for(i=1;i<=m;i++){cin>>x>>y>>z;if(x==y)continue;e[x].push_back({y,z});e[y].push_back({x,z});}memset(d,127,sizeof(d));spfa(1);cout<<(d[n]>9999999?-1:d[n]);return 0;
}

相关文章:

图的最短路径

最短路径算法对图结构没有特殊要求&#xff0c;不要求连通图&#xff0c;且有向图无向图均可。 最短路径算法目标是求得从某顶点出发&#xff0c;沿图的边到达另一顶点所经过的路径中&#xff0c;各边上权值之和最小的一条路径。解决最短路的问题有以下算法&#xff1a;Dijkst…...

RHCE----Shell变量和引用

1.变量的类型及含义 变量类型: 1、自定义变量: 在当前的shell命令行界面设置的变量是局部变量 例子&#xff1a; num1 namezhangsan 2、环境变量全局变量,通过export 导出后的局部变量是全局变量 、bash的初始化文件&#xff1a;/etc/profile&#xff1a;存放一些全局变量…...

【Redis】聊一下缓存雪崩、击穿、穿透、预热

缓存的引入带来了数据读取性能的提升&#xff0c;但是因此也引入新的问题&#xff0c;一个是数据双写一致性&#xff0c;另一个就是雪崩、击穿、穿透&#xff0c;那么如何解决这些问题&#xff0c;我们来说下对应的问题和解决方案 雪崩 缓存雪崩&#xff1a;同一时间内大量请…...

全景描绘云原生技术图谱,首个《云原生应用引擎技术发展白皮书》发布

5月12日&#xff0c;由神州数码主办、北京经开区国家信创园、中关村云计算产业联盟协办的2023通明湖论坛-云原生分论坛在京召开。论坛期间&#xff0c;神州数码联合北京通明湖信息技术应用创新中心、中国信通院和通明智云正式发布了《云原生应用引擎技术发展白皮书》&#xff0…...

【Python共享文件】——Python快速搭建HTTP web服务实现文件共享并公网远程访问

文章目录 1. 前言2. 视频教程3. 本地文件服务器搭建3.1 python的安装和设置3.2 cpolar的安装和注册 4. 本地文件服务器的发布4.1 Cpolar云端设置4.2 Cpolar本地设置 5. 公网访问测试6. 结语 1. 前言 数据共享作为和连接作为互联网的基础应用&#xff0c;不仅在商业和办公场景有…...

Mysql数据库分库分表

为什么使用分库分表&#xff1f; 传统的将数据集中存储至单一数据节点的解决方案&#xff0c;在性能、可用性和运维成本这三方面已经难于满足互联网的海量数据场景。 1&#xff09;性能 从性能方面来说&#xff0c;由于关系型数据库大多采用 B 树类型的索引&#xff0c;在数…...

SpringBoot热部署插件原理分析及实战演练

目录 1、关于热部署&#xff08;Hot Deploy&#xff09;产生的背景 1&#xff09;热部署出现前 2&#xff09;热部署出现后 2、spring-boot-devtools插件原理 1&#xff09;解决变更文件自动加载到JVM中 2&#xff09;spring-boot-devtools重启速度比手动重启快 3、关于…...

【C++ 入坑指南】(10)函数

文章目录 简介定义实例函数的分文件编写 简介 函数是一组一起执行一个任务的语句。每个 C 程序都至少有一个函数&#xff0c;即主函数 main() &#xff0c;所有简单的程序都可以定义其他额外的函数。 您可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定…...

P2233 [HNOI2002]公交车路线

题目描述 在长沙城新建的环城公路上一共有 8 个公交站&#xff0c;分别为 A、B、C、D、E、F、G、H。公共汽车只能够在相邻的两个公交站之间运行&#xff0c;因此你从某一个公交站到另外一个公交站往往要换几次车&#xff0c;例如从公交站 A 到公交站 D&#xff0c;你就至少需要…...

java入门-W11(K168-K182)网络编程

1. 网络编程入门 1.1 网络编程概述 计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备&#xff0c;通过通信线路连接起来&#xff0c;在网络操作系统&#xff0c;网络管理软件及网络通信协议的管理和协调下&#xff0c;实现资源共享和信息传递的计算机系统…...

距离6月18日DAMA-CDGA/CDGP认证考试还有31天,报名从速

6月18日DAMA-CDGA/CDGP数据治理认证考试开放报名中&#xff01; 考试开放地区&#xff1a;北京、上海、广州、深圳、长沙、呼和浩特、杭州、南京、济南、成都、西安。其他地区凑人数中… DAMA-CDGA/CDGP数据治理认证班进行中&#xff0c;报名从速&#xff01; DAMA认证为数据管…...

PO、VO、DAO、BO、DTO、POJO区分

一 分层领域模型规约: DO(Data Object):此对象与数据库表结构一一对应&#xff0c;通过 DAO 层向上传输数据源对象。DTO(Data Transfer Object):数据传输对象&#xff0c;Service 或 Manager 向外传输的对象。BO(Business Object):业务对象&#xff0c;由 Service 层输出的封装…...

MobPush Flutter平台插件

集成准备 注册账号 使用PushSDK之前&#xff0c;需要先在MobTech官网注册开发者账号&#xff0c;并获取MobTech提供的AppKey和AppSecret&#xff0c;详情可以点击查看注册流程 MobPush后台配置 注册MobTech账号后&#xff0c;需要在MobTech后台进行相关信息的配置&#xff…...

机器学习面试题库:K-means

一、简述K-means算法的原理及工作流程&#xff1f; 原理&#xff1a; K-means是一个无监督的聚类算法。它的主要目的是对同一组数据对象进行分类。其原理是基于样本间的相似性来聚类分析的&#xff0c;即将所有样本分为K个簇&#xff0c;使得同一个簇间中样本相似性最高&#…...

Linux:文本三剑客之awk

Linux&#xff1a;文本三剑客之awk 一、awk编辑器1.1 awk概述1.2 awk工作原理1.3 awk与sed的区别 二、awk的应用2.1 命令格式2.2 awk常见的内建变量&#xff08;可直接用&#xff09; 三、awk使用3.1 按行输出文本3.2 按字段输出文本3.3 通过管道、双引号调用 Shell 命令 一、a…...

如何借助Kafka持久化存储K8S事件数据?

大家应该对 Kubernetes Events 并不陌生&#xff0c;特别是当你使用 kubectl describe 命令或 Event API 资源来了解集群中的故障时。 $ kubectl get events15m Warning FailedCreate …...

一种基于非均匀分簇和建立簇间路由的算法的无线传感器网络路由协议(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 本文准备了一种路由方法&#xff0c;该方法使传感器通过有效地使用能量将数据从发送方加载到接收器&#xff0c;因为它在 LEAC…...

usb摄像头驱动打印信息

usb摄像头驱动打印信息 文章目录 usb摄像头驱动打印信息 在ubuntu中接入罗技c920摄像头打印的信息如下&#xff1a; [ 100.873222] usb 3-2: new high-speed USB device number 5 using xhci_hcd [ 101.230728] usb 3-2: New USB device found, idVendor046d, idProduct08e5 …...

银行半结构化和无领导群面注意事项

银行可以同时报考多家&#xff0c;因此部分同学也积累了不少宝贵的面试“失败”经验。今天小编就来给大家说说半结构化和无领导群面的注意事项&#xff0c;从如信银行考试中心了解到的整理如下&#xff1a; 一、半结构化面试注意事项&#xff1a; 半结构化面试更侧重于了解考生…...

今天公司来了个拿 30K 出来的测试,算是见识到了基础的天花板

今天上班开早会就是新人见面仪式&#xff0c;听说来了个很厉害的大佬&#xff0c;年纪还不大&#xff0c;是上家公司离职过来的&#xff0c;薪资已经达到中高等水平&#xff0c;很多人都好奇不已&#xff0c;能拿到这个薪资应该人不简单&#xff0c;果然&#xff0c;自我介绍的…...

OpenClaw智能监控:Qwen3-32B实现服务器异常自动告警

OpenClaw智能监控&#xff1a;Qwen3-32B实现服务器异常自动告警 1. 为什么选择OpenClaw做服务器监控&#xff1f; 去年我的个人博客经历了一次长达6小时的宕机&#xff0c;直到有读者发邮件反馈才发现问题。传统监控工具如Zabbix或Prometheus虽然功能强大&#xff0c;但配置复…...

[特殊字符] 第88课:目标和

想系统提升编程能力、查看更完整的学习路线&#xff0c;欢迎访问 AI Compass&#xff1a;https://github.com/tingaicompass/AI-Compass 仓库持续更新刷题题解、Python 基础和 AI 实战内容&#xff0c;适合想高效进阶的你。 &#x1f4d6; 第88课:目标和 模块:动态规划 | 难度:…...

揭秘OZON选品公司性价比:如何用最少的钱选出爆款?

在OZON平台上掘金&#xff0c;选品无疑是决定成败的第一步。然而&#xff0c;面对海量商品和瞬息万变的市场&#xff0c;许多卖家陷入了两难&#xff1a;要么投入大量时间和金钱盲目试错&#xff0c;要么依赖昂贵的选品工具&#xff0c;成本高企却收效甚微。今天&#xff0c;我…...

2026年AI决胜关键: Harness架构才是碾压对手的终极护城河!

文章指出&#xff0c;在AI领域&#xff0c;单纯依靠大模型参数已经无法决定胜负&#xff0c;真正关键的是Harness架构的稳定性。文章通过实证报告揭示&#xff0c;在底层大模型权重不变的情况下&#xff0c;精巧的Harness能使AI通过率大幅提升。文章详细分析了长任务Agent可能面…...

PlayRtttl嵌入式音频引擎:轻量级RTTTL/RTX解析与实时播放

1. PlayRtttl 库深度技术解析&#xff1a;嵌入式平台上的 RTTTL/RTX 音频引擎实现1.1 库定位与工程价值PlayRtttl 是一个面向资源受限嵌入式平台的轻量级 RTTTL&#xff08;Ring Tone Text Transfer Language&#xff09;与 RTX&#xff08;扩展版&#xff09;音频解析与播放库…...

基于MATLAB/Simulink的纯电动汽车模型( (包括驾驶员模型,电机模型,电池模型,传动模型,纵向动力学模型)

基于MATLAB/Simulink的纯电动汽车模型&#xff08; &#xff08;包括驾驶员模型&#xff0c;电机模型&#xff0c;电池模型&#xff0c;传动模型&#xff0c;纵向动力学模型&#xff09;&#xff0c;比较简单&#xff0c;适合零基础或初学者&#xff0c;标准的 Simulink 纯电动…...

Boodskap数字孪生Arduino客户端库深度解析

1. Boodskap IoT Digital Twin Arduino客户端库深度解析Boodskap IoT Digital Twin Arduino Client Library 是一款面向嵌入式边缘设备的轻量级物联网通信中间件&#xff0c;专为将Arduino生态&#xff08;尤其是ESP32系列&#xff09;传感器节点快速接入Boodskap Twinned数字孪…...

潘多拉魔盒上的封条:当AI强到连“造物主”都感到恐惧

梁敬彬梁敬弘兄弟出品 引言 2026年的春天&#xff0c;AI的狂飙似乎没有任何减速的迹象。各路媒体依然在为大模型跑分榜上的微小超越而摇旗呐喊&#xff0c;资本市场依然在为算力中心的落成而陷入狂热。在这场看似永远不会停歇的技术飙车中&#xff0c;几乎所有人都坚信一个朴…...

存储那么贵,何不白嫖飞书云文件空间荷

基础示例&#xff1a;单工作表 Excel 转 TXT 以下是将一个 Excel 文件中的第一个工作表转换为 TXT 的完整步骤&#xff1a; 1. 加载并读取Excel文件 from spire.xls import * from spire.xls.common import * workbook Workbook() workbook.LoadFromFile("示例.xlsx"…...

亚马逊向忠实Kindle用户“致谢“:停止支持旧款设备

亚马逊正以停止支持旧款设备的方式"回馈"长期忠实的Kindle用户&#xff0c;但同时也试图以新设备八折优惠及电子书购书抵用金来"降低影响"。正如科技领域的规律——没有任何设备能永远获得支持。亚马逊在今日发送给用户的邮件中宣布&#xff0c;自2026年5月…...