Jerry's Blog

Back

问题重现#

问题来自 洛谷-P4779,选取问题时稍作了更改.

题目:P4779【模板】单源最短路径

题目描述#

给出一个有向图,请输出从某一点出发到所有点的最短路径长度.

输入格式#

第一行包含三个整数 n,m,sn,m,s,分别表示点的个数、有向边的个数、出发点的编号.

接下来 mm 行每行包含三个整数 u,v,wu,v,w,表示一条 uvu \to v 的,长度为 ww 的边.

输出格式#

输出一行 nn 个整数,第 ii 个表示 ss 到第 ii 个点的最短路径,若不能到达则输出 23112^{31}-1

数据范围#

对于 100%100\% 的数据:1n1051 \leq n \leq 10^51m2×1051 \leq m \leq 2\times 10^51ui,vin1 \leq u_i, v_i\leq n0wi1090 \leq w_i \leq 10 ^ 90wi1090 \leq \sum w_i \leq 10 ^ 9

最短路算法#

注:为了表示方便,我们将从 aa 到点 bb 之间的边的权重表示为 g[a][b],如果没有边则为 INF

在介绍最短路之前,我们需要了解一个概念:松弛

我们已知有两个点 aabb,它们之间的最短距离为 g[a][b].我们尝试使用第三个点 cc,如果从 aa 点经过 cc 点再到 bb 点比从 aa 点直接到 bb 点所需要的路程少,则将最短距离更新.这样的操作叫做使用 cc 对从点 aa 到点 bb 之间的边进行松弛.

使用代码表示如下:

g[a][b] = max(g[a][b], g[a][c] + g[c][b]);
cpp

Floyd 算法#

Floyd 算法很简单,它的本质是动态规划.

我们首先定义一个二维数组 dist[i][j],表示从点 ii 到点 jj 的最短距离.输入数据时,类似邻接矩阵,直接将数据输入 dist 数组.

而后,枚举每一个 kk, ii, jj,尝试使用点 kk 对从点 ii 到点 jj 之间的边进行松弛.

枚举完成后,此时的 dist 数组就是最终的结果.

Floyd 算法不仅可以解决单源最短路的题目,还可以解决多源单目标最短路的问题.

但是,Floyd 算法太慢了,时间复杂度到达了 O(n3)O(n^3),因为基于邻接矩阵,空间复杂度也达到了 O(n2)O(n^2),所以只能拿到部分分.

SPFA 算法#

我们可以定义一个数组 dist[i],表示从源点 ssii 的最小距离.初始时每一项都是无穷大,而后将 dist[s] 设定为 0,表示从源点 ss 到本身的最小距离为 0.之后,对于每个目标点 ii (一开始是 ss )的每一个相邻节点 jj,都尝试使用点 ii 对从点 ss 到点 jj 的边进行松弛.而后,将 jj 选中为目标点,重复.直到没有待被选中的点位置,此时的 dist 数组就是最终的结果,类似于广度优先搜索.

SPFA 算法对于处理带有负权的图是最快的.

以下是基于链式前向星的源代码:

显然,SPFA 算法的时间复杂度在最坏的情况下为 O(nm)O(nm),仍旧无法拿到满分.

dijkstra 算法#

我们仍旧可以像 SPFA 一样,定义一个 dist 数组,不过,在松弛的时候,我们需要选取 dist 数组中最小的一个节点 ii,对于 ii 的每一个相邻节点 jj,都尝试使用 ii 来对从节点 ss 到节点 jj 的这条边进行松弛,直到每一个点都被选中作为点 ii 过,此时的 dist 数组就是最终的结果.

dijkstra 其实就是 SPFA 的贪心版本.

以下是基于链式前向星的源代码:

显然,dijkstra 算法的时间复杂度在最坏的情况下为 O(n2)O(n^2),仍旧无法拿到满分.此外,此算法无法处理含有负权边的图.

dijkstra 算法优化#

dijkstra 算法可以利用堆进行优化.

宏观整个算法,最浪费时间的事情就是找出 dist 中最小的一项,因此我们就想到了使用堆来优化.

在赛场上直接实现堆不太现实,因此我们可以使用 C++STL 优先队列来快速查找最小的一项.

以下是基于链式前向星的源代码:

这样的算法可以达到时间复杂度是 O(nlogn)O(n\log n),可以完成这道题目.

最短路算法比较#

算法时间复杂度是否可以有负权边使用场景
FloydO(n3)O(n^3)多源最短路
SPFA最差 O(nm)O(nm)在有负权时
dijkstraO(n2)O(n^2)建议使用其优化版
dijkstra 优化O(nlogn)O(n\log n)没有负权时

标程#

以下的代码在洛谷中提交后,100% 的样例是 AC 的.

最短路
https://blog.jerrylab.top/blog/graph/min-path
Author Jerry
Published at 2026年3月2日