给出具有 n 个顶点和 m 弧( n <1500,m <5000 )和一个弧的有向加权图(u,v)。并回答这个问题,即有多少最短路径(可以在 a 的任意位置开始,并在 b a!= b )穿过给定的弧。
示例:
n = 4,m = 4
重量为5的弧(1、2)
重量为5的弧(2,3)
重量为5的弧(3,4)
重量为8的弧(1、4)
和圆弧(1、2)。
答案是2,因为最短路径1-> 3和1-> 2中的弧线(1、2)。
Dijkstra可以解决这个问题吗?
答案 0 :(得分:2)
一个快速的想法是,由于它全部与路径重建有关,因此与在每个节点上运行Floyd-Warshall's algorithm
相比,您可以使用Dijkstra's algorithm
以更便宜的方式找到每对节点之间的最短路径。之后,通过对每个节点进行路径重构,您只需检查提供的弧线是否在找到的路径上即可。
(但是请注意,Floyd-Warshall的算法不支持负周期图)
答案 1 :(得分:0)
首先,使用Dijkstra的算法找出u和v之间的最短路径。有趣的是,如果u和v之间的最短路径不是边缘uv,则任何两个点之间的最短路径都不会包含边缘uv。在这种情况下,您可以将答案提交为0。
现在,我们可以继续在每个节点上使用 Floyd Warshall算法 O(n^3)
或使用Fibonacci堆使用 Dijkstra算法 O(m+n*logn)
是O(n*m + (n^2)*logn)
。我通常会推荐Floyd Warshall,但是由于m的最大值似乎不等于n的最大值的n ^ 2的数量级,因此如果您使用Fibonacci堆,Dijkstra在多个节点上的算法可能变得可行。 (m和n可能足够大以补偿使用大常数时的巨大常数。)
下一步
从每个点“ a”开始,查看到“ u”的最短路径长度+ len(u-> v)+从“ v”到“ b”的最短路径长度是否=从“ a”到“ b”的最短路径长度”。由于我们已经有了最短路径的表,因此每次检查应该花费固定的时间。这将是
n choose 2
的顺序,即O(n^2)
对于所有a和b,如果确实如此,则必须找出是否存在多个最短路径。这将是一个痛苦。无论是Dijkstra的算法还是Floyd Warshall的算法,都无法为您找到任意两点之间的所有最短路径。它们仅保证 a 最短的路径。暴力破解的一种方法可能是识别一条最短路径并一次更改一条边,以查看是否出现了一条新的最短路径!
这整个过程仍然应该比构造所有可能的路径更快,检查它是否最短,最后检查它是否穿过所需的边缘。但是,我很想知道我指定算法的后半部分是否可以优化或更改。
编辑:由于该图被称为有向无环图,因此一开始无需应用Bellman ford。如果您想知道在有向图中如何识别负边权重循环,请阅读有关Johnson's Algorithm的信息。