【问题标题】:Bellman-Ford: all shortest pathsBellman-Ford:所有最短路径
【发布时间】:2012-07-06 21:24:08
【问题描述】:

我已成功实施 Bellman-Ford,以在边缘具有负权重/距离时找到最短路径的距离。我无法让它返回所有最短路径(当有最短路径时)。我设法用 Dijkstra 获得了所有最短路径(在给定的一对节点之间)。 Bellman-Ford 有可能吗? (只是想知道我是否在浪费时间尝试)

【问题讨论】:

  • 在数学上,我不确定这是否可行。例如,如果所有边的成本为零,那么您可以采用无限多条可能的最短路径。你想要最短的非循环路径吗?
  • 是的,抱歉,应该指定。我想找到两个节点之间的所有最短非循环路径。

标签: algorithm shortest-path bellman-ford


【解决方案1】:

如果您稍微更改Bellman-Ford algorithm 的第二步,您可以实现非常相似的效果:

for i from 1 to size(vertices)-1:
   for each edge uv in edges: // uv is the edge from u to v
       u := uv.source
       v := uv.destination
       if u.distance + uv.weight < v.distance:
           v.distance := u.distance + uv.weight
           v.predecessor[] := u
       else if u.distance + uv.weight == v.distance:
           if u not in v.predecessor:
               v.predecessor += u

其中v.predecessor 是一个顶点列表。如果v 的新距离等于尚未包含的路径,则包含新的前任。

为了打印所有最短路径,您可以使用类似

procedure printPaths(vertex current, vertex start, list used, string path):
    if current == start:
        print start.id + " -> " + path
    else:
        for each edge ve in current.predecessors:
            if ve.start not in used:
                printPaths(ve.start,start, used + ve.start, ve.start.id + " -> " + path)

使用printPaths(stop,start,stop,stop.id) 打印所有路径。

注意:如果在算法完成后删除重复元素,则可以从修改后的算法中排除 if u not in v.predecessor then v.predecessor += u

【讨论】:

  • 感谢您的帮助。实际上,除了递归 printPaths 过程之外,我已经设法完成了所有事情,这在查看之后真的很简单。有没有办法在不递归的情况下打印所有路径?在更一般的意义上,是否总是可以使用循环而不是递归?
  • 是的,但是跟踪used 很棘手,因为这是一种回溯算法。如果您想创建一个迭代版本,您将不得不以某种方式操纵used 列表而不创建无限循环。有一些粗略的解决方案,例如构建一个queue[0,...,n-1],其中queue[i] 包含i 级别(queue[0] := [stop])的所有可能的前辈,并使用n 维多索引I 来迭代队列。但是您必须检查当前设置的I 是否有效。由于您只使用非循环路径,因此您可以使用used 的顶点集列表​​。
  • v.predecessor[] := u 和 v.predecessor += u 有什么区别?
  • @calibr v.predecessor[] := upredecessor 的列表设置为u 并且只是u,而v.predecessor += u 将其添加到列表中。该符号在某种程度上取自en.wikipedia.org/w/…
猜你喜欢
  • 1970-01-01
  • 2014-05-24
  • 1970-01-01
  • 2012-07-07
  • 1970-01-01
  • 2015-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多