搜索与图论第六期 最短路问题


前言

最短路问题真的很重要很重要希望大家都能够完全掌握所有最短路算法!!

一、最短路问题的分类

Dijkstra:


Dijkstra算法是一种著名的图算法,主要用于求解有权图中的单源最短路径问题。它由荷兰计算机科学家艾兹赫尔·戴克斯特拉(Edsger Wybe Dijkstra)在1956年首次提出。Dijkstra算法的核心思想是通过以下步骤逐步构建最短路径树:

初始化:创建一个空白的最短路径字典,其中每个节点的距离设置为无穷大,起始节点的距离设置为0。
标记已访问节点:创建一个已访问节点集合,并将所有节点都加入这个集合。
更新距离:对于未被访问的节点,从其未被访问的邻居中选择距离当前节点最近的邻居,将其标记为已访问,并且更新该邻居节点的距离。
重复上述步骤:直到所有节点都被访问,此时已经得到了从起始节点到所有其他节点的最短路径。
Dijkstra算法的特点在于它能够处理图中的负权边,但通常会忽略这些边,因为它们不会影响最终的路径长度计算。如果图中存在负权边,可能需要使用其他的图算法,如Bellman-Ford算法。此外,Dijkstra算法的时间复杂度通常是O(V^2),其中V是节点数量,但如果使用优先队列来优化,时间复杂度可以减少到O(Elog(V)),其中E是边数。1

在实际编程实现时,可以使用不同的数据结构和算法来实现Dijkstra算法,以提高效率。例如,可以使用优先队列或堆来加速松弛操作,从而减少总体时间复杂度。2

总结一下,Dijkstra算法的主要优点是可以有效地解决单源最短路径问题,并且在大多数情况下不需要考虑负权边的影响。它在多个领域有着广泛的应用,包括路线规划、网络路由、资源分配等。

Bellman-Ford算法:

贝尔曼-福特算法(Bellman-Ford Algorithm)是一种用于求解单源最短路径问题的算法,由理查德·贝尔曼(Richard Bellman)和莱斯特·福特(Lester Ford)共同创立。该算法能够处理图中的负权边,并具有简单的实现方式和较高的时间复杂度。贝尔曼-福特算法的核心思想是通过多次松弛操作来确定所有可能的最短路径。每次迭代中,算法会更新所有节点的距离,确保它们符合“三角不等式”,即任意两点间的距离加上第三者的重量小于或等于这两点间距离之和。

尽管贝尔曼-福特算法在处理带负权边的最短路径问题上表现良好,但在某些情况下可能会遇到困难,如当图中存在负权环路时,可能会导致无法找到任何有效的最短路径。此外,虽然它可以处理负权边,但其时间复杂度为 \( O(VE) \),其中 \( V \) 是顶点的数量,\( E \) 是边的数量,这使得它在实践中可能不是最佳选择。

总结来说,贝尔曼-福特算法的主要优点包括支持负权边和简单性,而其主要缺点在于高的时间复杂度。为了提高效率,算法可以进行一些优化措施。需要注意的是,贝尔曼-福特算法有时也被称作 Moore-Bellman-Ford 算法,因为它还涉及到了另一位科学家 Edward F. Moore 的贡献。

SPFA算法:

SPFA算法
SPFA 算法是 Bellman-Ford算法 的队列优化算法的别称,通常用于求含负权边的单源最短路径,以及判负权环

Floyd算法:

floyd算法
Floyd算法,也被称为弗洛伊德算法或插点法,是一种解决加权图中顶点间最短路径问题的算法。它可以处理有向图或负权图(但不能存在负权回路),并同时用于计算有向图的传递闭包。Floyd算法的名称来源于其创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德。

Floyd算法的核心思想是利用动态规划技术来构建一个路径矩阵,这个矩阵包含了图中所有顶点对之间的最短路径长度。算法的基本步骤包括初始化路径矩阵、进行多次更新操作以及最终获取任意两点之间的最短路径。

具体来说,算法会创建两个矩阵:一个存储了顶点对之间的距离,另一个存储了这些距离的逆。在每一次迭代中,都会根据已有的信息更新这两个矩阵。这个过程涉及到多个嵌套的for循环,直到所有的路径都被计算出来为止。

Floyd算法的时间复杂度和空间复杂度分别为O(n^3)和O(n^2),这意味着它在处理大规模网络图时会比较耗时。此外,虽然算法本身不需要回溯路径的具体信息,但它确实可以用来构造出最短路径的详细列表。

总结一下,Floyd算法的主要特点和应用场景如下:

适用范围:适用于有向图或负权图,不能有负权回路。
时间复杂度:O(n^3),即n³次操作。
空间复杂度:O(n^2),即n²个变量。
主要用途:求解任意两点间的最短路径,也可以用于计算传递闭包。
其他应用:在某些情况下,可以用于查找关系的传递闭包。

二、例题

1.朴素Dijkstra:


AC代码:

#include<bits/stdc++.h>using namespace std;const int N = 510;
int g[N][N];
int dis[N];
bool st[N];
int n,m;
int dij()
{memset(dis,0x3f,sizeof dis);dis[1] = 0;for(int i=0;i<n;i++){int t = -1;for(int j=1;j<=n;j++){if(!st[j] && (t==-1 || dis[t]>dis[j]))t=j;}st[t] = true;for(int j=1;j <= n;j++){dis[j] = min(dis[t]+g[t][j],dis[j]);}}if(dis[n] == 0x3f3f3f3f) return -1;return dis[n];
}
int main()
{cin>>n>>m;memset(g,0x3f,sizeof g);while(m--){int a,b,c;scanf("%d%d%d",&a,&b,&c);g[a][b] = min(g[a][b],c);}int t = dij();cout<<t<<endl;return 0;
}

2、堆优化Dijkstra:

AC代码:

#include<bits/stdc++.h>using namespace std;const int N = 15e4+10; 
typedef pair<int ,int>PII;
int h[N],e[N],ne[N],idx,w[N];
int n,m;
int dis[N],st[N];
void add(int a,int b,int c)
{e[idx] = b,w[idx] = c,ne[idx] = h[a],h[a] = idx ++;
}int dij()
{memset(dis,0x3f,sizeof dis);dis[1] = 0;priority_queue<PII,vector<PII>,greater<PII>>heap;heap.push({0,1});//距离加顶点;while(heap.size()){auto t = heap.top();heap.pop();int ver = t.second,distance = t.first;if(st[ver]) continue;st[ver] = true;for(int i=h[ver];i!=-1;i= ne[i]){int j = e[i];//为了更新其他的边if(dis[j] > w[i] + dis[ver] && !st[j]){dis[j]  =w[i]+ dis[ver];heap.push({dis[j],j});}}}if(dis[n] == 0x3f3f3f3f ) return -1;return dis[n];
}
int main()
{cin>>n>>m;memset(h,-1,sizeof h);while(m--){int a,b,c;cin>>a>>b>>c;add(a,b,c);}cout<<dij()<<endl;return 0;
}

3、 有边数限制的最短路:

AC代码:

#include<bits/stdc++.h>using namespace std;const int N = 520,M = 10010;
int n,m,k;
int dis[N],backup[M];struct Edge
{int a,b,w;
}edges[M];int bellman_ford()
{memset(dis,0x3f,sizeof dis);dis[1] = 0;for(int i = 0; i < k; i ++){memcpy(backup,dis,sizeof dis);for(int j=0;j< m;j ++){int a = edges[j].a,b=edges[j].b,w=edges[j].w;dis[b] = min(dis[b],backup[a] + w);}}if(dis[n] > 0x3f3f3f3f/2 ) return -1;return dis[n];
}
int main()
{cin>>n>>m>>k;for(int i=0;i<m;i++){int a,b,w;scanf("%d%d%d",&a,&b,&w);edges[i] = {a,b,w};}int t = bellman_ford();if(t == -1) puts("impossible");else printf("%d\n",t);return 0;
}

4、spfa判断负环:

AC代码:

#include<bits/stdc++.h>using namespace std;const int N = 15e4+10; 
typedef pair<int ,int>PII;
int h[N],e[N],ne[N],idx,w[N];
int n,m;
int dis[N],st[N],cnt[N];
void add(int a,int b,int c)
{e[idx] = b,w[idx] = c,ne[idx] = h[a],h[a] = idx ++;
}int spfa()
{dis[1] = 0;queue<int>q;for(int i=1;i<=n;i++){st[i]= true;q.push(i);}while(q.size()){int t = q.front();q.pop();st[t]  = false;for(int i=h[t];i!=-1;i = ne[i]){int j= e[i];if(dis[j] > dis[t] + w[i]){dis[j] = dis[t]+w[i];cnt[j] = cnt[t] + 1;if(cnt[j]>=n) return true; q.push(j);st[j] = true;}}}return false;
}
int main()
{cin>>n>>m;memset(h,-1,sizeof h);while(m--){int a,b,c;cin>>a>>b>>c;add(a,b,c);}if(spfa()) puts("Yes");else puts("No");return 0;
}

5、spfa求最短路:

AC代码:

#include<bits/stdc++.h>using namespace std;const int N = 15e4+10; 
typedef pair<int ,int>PII;
int h[N],e[N],ne[N],idx,w[N];
int n,m;
int dis[N],st[N];
void add(int a,int b,int c)
{e[idx] = b,w[idx] = c,ne[idx] = h[a],h[a] = idx ++;
}int dij()
{memset(dis,0x3f,sizeof dis);dis[1] = 0;queue<int>q;q.push(1);st[1] = true;while(q.size()){int t = q.front();q.pop();st[t]  = false;for(int i=h[t];i!=-1;i = ne[i]){int j= e[i];if(dis[j] > dis[t] + w[i]){dis[j] = dis[t]+w[i];q.push(j);st[j] = true;}}}if(dis[n] == 0x3f3f3f3f) return -1;return dis[n];
}
int main()
{cin>>n>>m;memset(h,-1,sizeof h);while(m--){int a,b,c;cin>>a>>b>>c;add(a,b,c);}int t = dij();if(t == -1) puts("impossible");else cout<<t<<endl;return 0;
}

6、Floyd求最短路:

AC代码:

#include<bits/stdc++.h>using namespace std;const int N = 210,INF= 1e9;int n,m,q;
int d[N][N];
int main()
{cin>>n>>m>>q;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(i == j) d[i][j] == 0;else d[i][j] = INF;}}while(m--){int a,b,w;scanf("%d%d%d",&a,&b,&w);d[a][b] = min(d[a][b],w);}for(int k=1;k<=n;k++){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){d[i][j] = min(d[i][j],d[i][k]+d[k][j]);}}}while(q--){int a,b;scanf("%d%d",&a,&b);if(d[a][b]>INF/2) puts("impossible");else printf("%d\n",d[a][b]);}return 0;
}

总结:这部分真的特别特别的重要,希望大家能够完全掌握,对以后的面试也有帮助的,感谢大家的观看!!!

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

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

相关文章

Go 入门

1. hello&#xff0c;world hello&#xff0c;world hello&#xff0c;world 经典示例 package main import "fmt" func main() { fmt.Println("你好&#xff0c;Go") } Go 基础知识Go 是编译型的语言Go 的工具链将程序的源文件转变成机器相关的原…

小红书达人推广模式有哪些,品牌投放策略总结

小红书是一个以种草为核心的平台&#xff0c;而品牌方进行种草时&#xff0c;就需要依托达人的力量。今天我们和大家分享下小红书达人推广模式有哪些&#xff0c;品牌投放策略总结&#xff01; 一、小红书达人推广模式有哪些 1. 明星种草 这种小红书达人推广模式&#xff0c;依…

BioXCell--RecombiMAb anti-mouse CTLA-4 (CD152) (LALA-PG)

9D9-CP008单克隆抗体是原始9D9单克隆抗体的重组嵌合型抗体。可变结构域序列与原始9D9克隆号相同&#xff0c;但是恒定区序列已经从小鼠IgG2b变为小鼠IgG2a。9D9-CP008单克隆抗体在Fc片段中也含有LALA-PG突变&#xff0c;使其无法与内源性Fcγ受体结合。 9D9-CP008单克隆抗体能与…

vue封装接口

目录 封装接口前缀 配置逻辑 接口存放文件 配置代理 获取数据方法 封装接口前缀 config.js const serverConfig {baseURL: "https://xxx.xxxxxxxx.com/api", // 请求基础地址,可根据环境自定义useTokenAuthorization: false, // 是否开启 token 认证};export …

【手写数据库toadb】02 开发数据库内核准备阶段-git工具使用

git工具使用 开发环境 ​专栏内容: 手写数据库toadb 本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。 本专栏会定期更新,对应的代码也会定期更新,每个阶段的代码会打上tag,…

langchain中的Document类

在Langchain-Chatchat的上传文档接口&#xff08;upload_docs&#xff09;中有个自定义的docs字段&#xff0c;用到了Document类。根据发现指的是from langchain.docstore.document import Document。本文简要对Document类进行介绍。 1.上传文档接口upload_docs def upload_d…

检测到目标SSL证书已过期怎么回事?

在浏览网站时&#xff0c;有时会遇到一个警告&#xff0c;提示目标SSL证书已过期。这是一个令人担忧的信号&#xff0c;意味着网站的安全性可能存在问题。那么&#xff0c;为什么会出现目标SSL证书过期的情况&#xff1f;我们该如何应对呢&#xff1f; 首先&#xff0c;我们需要…

LCD-LMD-PSO-ELM的电能质量分类,LCD特征提取,LMD特征提取,粒子群算法优化极限学习机

目录 背影 极限学习机 LCD-LMD-PSO-ELM的电能质量分类,LCD特征提取,LMD特征提取,粒子群算法优化极限学习机 主要参数 MATLAB代码 效果图 结果分析 展望 完整代码下载链接:LCD-LMD-PSO-ELM的电能质量分类,LCD特征提取,LMD特征提取,粒子群算法优化极限学习机资源-CSDN文库…

【C语言进阶】预处理详解

引言 对预处理的相关知识进行详细的介绍 ✨ 猪巴戒&#xff1a;个人主页✨ 所属专栏&#xff1a;《C语言进阶》 &#x1f388;跟着猪巴戒&#xff0c;一起学习C语言&#x1f388; 目录 引言 预定义符号 #define定义常量 #define定义宏 带有副作用的宏参数 宏替换的规则 …

理解LSTM一种递归神经网络(RNN)

1 递归神经网络结构 一个简单的传统神经网络结构如下图所示&#xff1a; 给他一些输入x0,x1,x2 … xt, 经过神经元作用之后得到一些对应的输出h0,h1,h2 … ht。每次的训练&#xff0c;神经元和神经元之间不需要传递任何信息。 递归神经网络和传统神经网络不同的一个点在于&am…

Linux 网络传输学习笔记

这篇是混合《Linux性能优化实战》以及 《Wireshark网络分析就这么简单》的一些关于Linux 网络的学习概念和知识点笔记 &#xff0c;主要记录网络传输流程以及对于TCP和UDP传输的一些影响因素 Linux 网络传输流程 借用一张倪朋飞先生的《Linux性能优化实战》课程中的图片 接收流…

利用STM32CubeMX和keil模拟器,3天入门FreeRTOS(2.1) —— 任务挂起和恢复

前言 &#xff08;1&#xff09;FreeRTOS是我一天过完的&#xff0c;由此回忆并且记录一下。个人认为&#xff0c;如果只是入门&#xff0c;利用STM32CubeMX是一个非常好的选择。学习完本系列课程之后&#xff0c;再去学习网上的一些其他课程也许会简单很多。 &#xff08;2&am…

SpringBoot整合FreeMarker

FreeMarker FreeMarker 是一个模板引擎&#xff0c;可以将模板与数据结合生成文本输出。以下是 Java FreeMarker 常用的语法及示例&#xff1a; 输出变量值 使用 ${} 输出变量值&#xff0c;如&#xff1a; ${user.name}条件判断 使用 <#if> 和 <#else> 进行条…

IDEA内置HTTP CLIENT

使用IDEA进行HTTP测试两种方法&#xff1a; a. 在controller层的方法中点击小地球跳转&#xff08;因为方法上带有RequestMapping注解&#xff0c;IDEA识别到这是一个handler&#xff09; b. 在全局任意位置新建右键新建一个HTTP Request&#xff0c;即自动新建一个测试文件。每…

Windows 下ffmpeg安装及实践

Windows 下ffmpeg安装及实践 背景安装实践其他 背景 最近负责音频文件处理相关的业务&#xff0c;涉及到 ffmpeg 对一些音频文件格式的校验&#xff0c;记录一下安装过程及踩坑过程。 安装 如图1所示&#xff0c;进入官网&#xff0c;在windows下任选一个文件&#xff1a;h…

C# 创建多线程的函数

C#中&#xff0c;创建子线程与Task任务相比&#xff0c;能够循环执行特定操作&#xff0c;可以用于长期监听TCP消息&#xff0c;发送心跳等。 本文对C#的多线程简单封装一下&#xff0c;哎&#xff0c;以方便线程的创建和命名。 文章目录 多线程定义应用 多线程 定义 using S…

git如何导出提交记录及修改的文件清单?

导出git提交日志及修改文件 # 所有人的提交记录 git log --pretty=format:"%ai,%an:%s" --since="10 day ago" >> ~/Desktop/commit10.log#某一个人的提交记录 git log --pretty=format:"%ai,%an:%s" --since="30 day ago" |

基于核极限学习机的回归分析,基于极限学习机的预测

目录 背影 极限学习机 基于核极限学习机的回归分析 主要参数 MATLAB代码 效果图 结果分析 展望 完整代码下载链接:(代码完整,数据齐全)资源-CSDN文库 https://download.csdn.net/download/abc991835105/88768798 背影 极限学习机是在BP神经网络上改进的一种网络,拥有无…

EMC、磁珠、磁环、ESD

1.EMC 1.1概念 EMC-电磁兼容性&#xff0c;是指设备在其电磁环境中符合要求运行并且不对其环境中的任何设备产生无法忍受的电磁干扰的能力。 EMC包括两个方面的要求&#xff1a; ①、设备在正常运行过程中对所在环境产生的电磁干扰不能超过一定的限值 ②、设备对所在环境中…

互联网摸鱼日报(2024-01-22)

互联网摸鱼日报(2024-01-22) 开源中国资讯 Stability AI 推出更小、更高效的 1.6B 语言模型 X 正面向 Android 推出音频和视频通话 Extism —— WebAssembly 插件实现框架 Gitee 推荐 | 龙蜥社区最佳安全加固实践指南 security-benchmark 每日一博 | 得物云原生容器技术探…