我得到了一个有向图,其中每个边都有成本。由于图中最多有两个负边的事实,我的目标是找到从给定节点到所有节点的最短路径距离在V.算法的时间复杂度应为O(|E| + |V|*log|V|)
,所以我认为我需要应用Dijkstra的算法。
我猜我需要将我的给定图形以某种方式转换为具有非负权重的新图形,该图形中从s到v的最短路径将等于给定图形中所需的最短路径。或者也许我需要修改Dijkstra的算法?
我现在正在努力。任何帮助将不胜感激!
答案 0 :(得分:2)
由于Dijkstra的算法是贪婪的,因此它不适用于负权重。为此需要一些其他算法,如the Bellman-Ford Algorithm。
但是,如果你仍然想使用Dijkstra的算法,那么就有一种已知的方法。在这种方法中,您需要重新分配成本,以便所有成本都变为正值。
为此您可以查看 Johnson的算法。约翰逊的算法包括以下步骤(取自Wikipedia):
答案 1 :(得分:2)
只需要开始一些定义:
让负边为n1 = (n1s, n1e)
(即从顶点n1s
到顶点n1e
)
和n2 = (n2s, n2e)
。
将我们想要查找的最短路径的起点和终点分别定义为s
和e
。
基本理念:
对负起重量边缘的起始顶点和每个末端顶点的每个组合运行Dijkstra算法多次,作为起始点和结束顶点以及负权重边缘的每个起始顶点作为结束点,并使用这些值可以找到实际的最短路径。
算法:
使用Dijkstra算法确定以下最短路径,所有这些路径都排除了两个负边缘:
se = s -> e // shortest path from s to e
sn1 = s -> n1s // shortest path from s to n1
sn2 = s -> n2s // shortest path from s to n2
ne1 = n1e -> e // shortest path from n1 to e
n1n2 = n1e -> n2s // shortest path from n1 to n2
ne2 = n2e -> e // shortest path from n2 to e
n2n1 = n2e -> n1s // shortest path from n2 to n1
现在只需计算最小值:
se // s to e
sn1 + n1 + ne1 // s to n1 to e
sn2 + n2 + ne2 // s to n2 to e
sn1 + n1 + n1n2 + n2 + ne2 // s to n1 to n2 to e
sn2 + n2 + n2n1 + n1 + ne1 // s to n2 to n1 to e
由于Dijkstra算法有7次运行,因此
运行时间为O(7(|E| + |V| log |V|))
= O(|E| + |V| log |V|)
。