SOFA 的最差测试用例

Worst test case for SPFA

最近看了最短路径加速算法。我想知道如何构建一个测试用例,对于该测试用例,SPFA 的标准实现会非常非常慢。你知道吗?

按照标准实施,我指的是来自维基百科的这个:

 procedure Shortest-Path-Faster-Algorithm(G, s)
1    for each vertex v ≠ s in V(G)
2        d(v) := ∞
3    d(s) := 0
4    offer s into Q
5    while Q is not empty
6        u := poll Q
7        for each edge (u, v) in E(G)
8            if d(u) + w(u, v) < d(v) then
9                d(v) := d(u) + w(u, v)
10                if v is not in Q then
11                    offer v into Q

例如。有N个顶点。第一个顶点是起点,第 N 个顶点是终点。对于第 i 个顶点,有 2 条边:(i, i+1, 1) 和 (1, i, 2*N) 其中 (a,b,c) 表示存在从 a 到 b 的边,权重为 c.

很容易看出这张图的最短路径是1->2->3->4->...->N。 假设对于 spfa 算法的第 7 行:对于 E(G) 中的每条边 (u, v),具有较大 id 的顶点在具有较小 id 的顶点之前被访问。然后第 i 个顶点将被推入队列 max(1,i-1) 次。所以总的执行时间是 O(N^2).

此外,如果对于第7行,id大的顶点比id小的顶点更晚被访问,则执行时间为O(N)。

对于spfa,总会存在时间复杂度最差的第7行的遍历顺序,也总是存在时间复杂度最好的第7行的遍历顺序。关键是信息如何通过最短路径传播。

根据 Ke Yang 的回答,具有 5 个顶点的图的最坏情况是:

在每次迭代中,队列将包含以下元素(队列的头部是最左边的元素):

[1]
[5, 4, 3, 2]
[4, 3, 2]
[3, 2]
[2]
[5, 4, 3]
[4, 3]
[3]
[5, 4]
[4]
[5]

这显示了一个模式:4 + 3 + 2 + 1,这表明它的 O(N^2)。

但是仔细观察,每次轮询(出队)一个顶点时,它的所有出站边都会被考虑,第 7 行。因此第 8 行中的 if 被执行:

Vertex Times dequed Outbound edges total execution of if
1 1 4 4
2 1 3 3
3 2 2 4
4 3 1 3
5 4 0 4

我们总共有: if执行次数:

复杂度为O(V^3),其中V为顶点数。因为这个示例图会很密集,有 O(V^2) 条边。最终的复杂度可以写成 O(V*E),其中 E 是边的数量。与 SPFA 最坏情况的复杂性相同。 https://en.wikipedia.org/wiki/Shortest_Path_Faster_Algorithm#Worst-case_performance