最短路学习笔记

最短路学习笔记

这是一篇复习笔记,相对写的比较简单,勿喷 qwq。

本文均考虑双向边。

本文代码合集

1. FloydFloyd

利用了 dpdp 的思想,是最基础的最短路算法。

我们考虑 dpi,jdp_{i,j} 表示 iijj 的最短路径。初始化为一个无穷大的值。

如果有 iijj 之间有连边的话,我们就先把 dpi,jdp_{i,j}dpj,idp_{j,i} 赋成这最初的值,也就是初始化。

考虑转移,我们枚举一个中转的点 kkiijj 的路径就可以表示成 iijj 的路径,加上 jjkk 的路径。

所以方程就是:

dpi,j=min(dpi,j,dpi,k+dpj,k)dp_{i,j}=min(dp_{i,j},dp_{i,k}+dp_{j,k})

在实现的时候应该注意,kk 要放在最外层循环。

如果 i,ki,k 或者 j,kj,k ,或者 i,ki,kj,kj,k 都没有路径之间,由于我们初值是一个无穷大的值,按照如上方程,不可能更新 dpi,jdp_{i,j}

时间:O(n3)O(n^3),空间 O(n2)O(n^2)

除非 nn 较小,不然不常用,一般是用在双重 dpdp 上。

同时一般使用邻接矩阵存图。

2. DijkatraDijkatra

通过这个算法,我们可以快速的求出从一个指定点 ss 到任意点的最短路,但是前提是边权必须为非负数

对于一个点,我们每次选择和他连边边权最小的点一直往下走,同时对这个点相连的所有点进行最短路的更新。也就是贪心的思想,这样可以保证更新的点的最短路一定是当前能走到的最短的路径。

注意走过的点不可以不可以重复,避免没用的更新。

这样做的时间是 n2n^2 的,考虑进行优化。

由于我们枚举边权最小的点进行更新的时候,时间是 O(n)O(n) 的,如果我们考虑使用小根堆维护当前的边权最小,那就可以达到 log(m)log(m) 的时间复杂度。

时间复杂度:O(mlogm)O(mlogm)

空间复杂度 : O(n)O(n)

3. SPFASPFA

考虑 DijkstraDijkstra 的更新的时候,是通过当前遍历到的 uu,不断地对 vv 进行更新最短路,也就是所谓的“松弛操作”。

我们考虑用一个队列维护可能可以进行松弛操作的点,对于一个点来说,如果他进行了松弛操作,显然他所连接的其他节点也有可能进行松弛操作,我们就把他们入队。

注意,一个节点不可以重复入队。

关于 SPFASPFA,他死了。

死的原因在于,由于他的本质是 BellmanfordBellman-ford 算法,本质就是对每一个点,对图上所有的边都进行一次松弛操作,所以最坏的情况下,他可能被卡到 O(nm)O(nm) 的时间复杂度

但是他的优势在于,他可以处理带有负权的图,同时可以判断负环。

时间:O(m)O(m)~O(nm)O(nm)

空间:O(n)O(n)

4. 分层图最短路

就是,大概用在图的结构不修改,但是边权可以被改变 kk 次。

做法大概是你把原图复制 k+1k+1 次,从 00 开始标号。看成一个一个“层”,在层与层之间,对原图可以操作的边在层和层之间的对应点连上单向边

这下你就可以发现,你走完多少层,就相当于进行了多少次操作。因为你连的是单向边,所以你不能从 i+1i+1 层跳回去 ii 层了。所以上面的结论显然。

然后你再跑最短路即可。

对于你跑最短路中可能经过相同的边,就是在层和层之间相同的边。不难发现这样一定不优,这不会被统计到答案。

5. JohnsonJohnson 全源最短路

不会,咕咕咕。到时候学了再补。

6.次短路& kk 短路

不会,咕咕咕,到时候学了再补。

posted @   June_Failure  阅读(2)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示