在包含至多两个负边的图中查找最短路径距离

时间:2014-02-04 15:49:11

标签: algorithm graph dijkstra shortest-path

我得到了一个有向图,其中每个边都有成本。由于图中最多有两个负边的事实,我的目标是找到从给定节点到所有节点的最短路径距离在V.算法的时间复杂度应为O(|E| + |V|*log|V|),所以我认为我需要应用Dijkstra的算法。

我猜我需要将我的给定图形以某种方式转换为具有非负权重的新图形,该图形中从s到v的最短路径将等于给定图形中所需的最短路径。或者也许我需要修改Dijkstra的算法?

我现在正在努力。任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:2)

由于Dijkstra的算法是贪婪的,因此它不适用于负权重。为此需要一些其他算法,如the Bellman-Ford Algorithm

但是,如果你仍然想使用Dijkstra的算法,那么就有一种已知的方法。在这种方法中,您需要重新分配成本,以便所有成本都变为正值。

为此您可以查看 Johnson的算法。约翰逊的算法包括以下步骤(取自Wikipedia):

  1. 首先,新的节点q被添加到图表中,通过零权重边缘连接到每个其他节点。
  2. 其次,使用Bellman-Ford算法,从新的顶点q开始,为每个顶点v找到从q到v的路径的最小权重h(v)。如果该步骤检测到负循环,则算法终止。
  3. 接下来,使用Bellman-Ford算法计算的值重新加权原始图的边缘:从u到v的边,长度为w(u,v),给出新的长度w(u,v) + h(u) - h(v)。
  4. 最后,q被删除,Dijkstra算法用于查找重新加权图中每个节点到每个其他顶点的最短路径。

答案 1 :(得分:2)

只需要开始一些定义:

  • 让负边为n1 = (n1s, n1e)(即从顶点n1s到顶点n1e
    n2 = (n2s, n2e)

  • 将我们想要查找的最短路径的起点和终点分别定义为se

基本理念:

对负起重量边缘的起始顶点和每个末端顶点的每个组合运行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|)