稀疏图上更快的单源最短路算法
TL;DR:这是一个求解无向图(非负实数边权)上单源最短路问题,期望复杂度为
O(n \sqrt{\log n \log \log n}) 的非确定性做法。(以下讨论均默认n,m 同阶)
做法来源:WC 2025 讲课。原论文见 link。
回忆 dijkstra 为什么无法突破
那么如何绕开排序呢?一个想法是,我们选出若干个关键点,然后把剩下的点挂在关键点上,关键点间按照最短路从小到大做,剩下的点跟着关键点更新即可。由于关键点数量是
事实上,这一算法就是这么做的。
默认图连通,定义
设定阈值
- 定义
b_u 为离其最近的关键点; - 定义
\text{Ball}_u = \{v | dis_{u,v} < dis_{u,b_u}\} ; - 容易发现
\text{Ball}_u 的期望大小是O(B) 。
此外,对于关键点
考虑如何求出
所以在运行这一算法前,我们要先对图结构做一些改造。对于一个原图上度数为
好了我们现在在期望
-
定义
d_x 为当前找到的起点到x 的最短路长度。 -
使用一个堆维护所有关键点,取出目前
d(\cdot) 最小的关键点p ,我们希望现在d_p = dis_{s,p} (1); -
我们接下来能顺路把
\text{Bundle}_p 内所有点的最短路算对(2)。
下面是算法过程,证明有空补:
- 只要在松弛点
u 的时候顺带更新b_u 就可以满足第一个要求; - 对于第二个要求,我们枚举所有
u \in \text{Bundle}_p ,枚举\text{Ball}_p \cup N(\text{Ball}_p) 内的所有点更新d_u ;更新完成后d_u=dis_{s,u} ,再用d_u 更新所有N(u) 和\{i \in \text{Ball}(p) | p \in N(u)\} 。
算一下复杂度,这里的复杂度是
代码并不是特别难写。常数还行,不过也不是特别小。空间常数很大。代码可以见 loj。
upd:没用