GESP202603 八级真题 · 拔高 · 6/22 最短路

P15805 子图最短路

对所有区间 [ℓ,r] 的子图求点对最短路之和。固定左端点 ℓ,右端点逐个加点跑“增量 Floyd”,顺手累加。

一、先回答问题

结论

枚举左端点 ℓ;让 r 从 ℓ 往右每次加入一个新点。 新点既是新端点、也是新中转点,用它跑一层 Floyd 即可把 [ℓ,r-1] 的最短路升级成 [ℓ,r] 的。

为什么不能硬跑

每个子图从头 Floyd 是 O(n⁵)=1e10。 增量加点后,整体约 n⁴/24≈4e6,n=100 轻松过。

二、核心观察

增量加点 = 多一个中转点

Floyd 的本质:dist[i][j] 是“只许用某个中转点集合”时的最短路。 把点 r 加进来,就是多了一个允许的中转点

① 接好 r 的直接边、把 r 的行列补成最优; ② 以 r 为中转更新所有点对 dist[i][j]=min(dist[i][j], dist[i][r]+dist[r][j])。 完事后当前矩阵就是子图 [ℓ,r] 的全源最短路。

三、互动演示:ℓ=1 时逐点加入(样例一)

图:1—2 权 1,2—3 权 2。蓝格是已算好的最短距离,黄格是刚加入的新点 r。灰格表示该点还没进子图。

新加入的点 r 已求出的最短路 未进入子图

四、自己选答案

Q1. 为什么固定左端点、只往右加点能省时间?

Q2. 加入新点 r 后,关键的一步更新是?

Q3. 两点在子图里不连通,距离按什么计入答案?

五、手推结果(总和 = 9)

子图 [ℓ,r]可达点对距离小计
[1,2]d(1,2)=11
[1,3]d(1,2)=1, d(1,3)=3, d(2,3)=26
[2,3]d(2,3)=22
其余(单点)无点对0
总和9

六、C++14 参考代码

枚举 ℓ + 增量加点 Floyd
① 无向图 + 重边,初始 e[u][v] 取最小边权。
② 不连通(仍是 INF)按题意记 0,跳过不累加
③ 边权到 1e6、点数 100,距离和会超 int,用 long long 并随时取模。

七、接着练(同梯度)