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
既然有's a constant 7 runs of Dijkstra'的算法, 运行时间为 O(7(|E| + |V| log |V|)) = O(|E| + |V| log |V|) .
2 回答
由于Dijkstra 's algorithm is greedy, it won'吨使用负权重 . 为此需要一些其他算法,如the Bellman-Ford Algorithm .
但是,如果您仍想使用Dijkstra算法,则有一种已知的方法 . 在这种方法中,您需要重新分配成本,以便所有成本都变为正数 .
为此你可以看看 Johnson's Algorithm . 约翰逊的算法包括以下步骤(取自Wikipedia):
首先,将新节点q添加到图形中,通过零权重边缘连接到每个其他节点 .
其次,使用Bellman-Ford算法,从新的顶点q开始,为每个顶点v找到从q到v的路径的最小权重h(v) . 如果此步骤检测到负循环,则算法为终止 .
接下来,使用Bellman-Ford算法计算的值重新加权原始图的边缘:从u到v的边,长度为w(u,v),给出新的长度w(u,v)h( u) - h(v) .
最后,q被移除,Dijkstra算法用于找到从重新加权图中每个节点到每个其他顶点的最短路径 .
Just some definitions to start:
设负边是
n1 = (n1s, n1e)
(即从顶点n1s
到顶点n1e
)和
n2 = (n2s, n2e)
.将要查找的最短路径的起始和结束顶点分别定义为
s
和e
.The basic idea:
对负起重量边缘的起始顶点和每个末端顶点的每个组合运行Dijkstra算法多次,作为起始点和末端顶点以及负权重边缘的每个起始顶点作为结束点,并使用这些值找到实际的最短路径 .
The algorithm:
既然有's a constant 7 runs of Dijkstra'的算法,
运行时间为
O(7(|E| + |V| log |V|))
=O(|E| + |V| log |V|)
.