我已经成功地实现了Bellman-Ford算法来查找具有负权重/距离的边的最短路径距离。但是,我无法让它返回所有最短路径(当最短路径存在并列情况时)。我使用Dijkstra算法成功地获得了所有最短路径(在给定节点对之间)。Bellman-Ford算法能否实现这一点?(只是想知道我是否在浪费时间尝试)
我已经成功地实现了Bellman-Ford算法来查找具有负权重/距离的边的最短路径距离。但是,我无法让它返回所有最短路径(当最短路径存在并列情况时)。我使用Dijkstra算法成功地获得了所有最短路径(在给定节点对之间)。Bellman-Ford算法能否实现这一点?(只是想知道我是否在浪费时间尝试)
如果你稍微修改贝尔曼-福特算法的第二步,你可以实现非常相似的效果:
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
if u.distance == INFINITY:
// skip start nodes that have no valid path from source yet
continue
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
从修改的算法中排除。
queue [0,...,n-1]
,其中queue [i]
包含第i
级的所有可能的前任(queue [0]:=[stop]
),并使用n维多索引I
来迭代队列。但您必须检查当前集合“I”是否有效。由于您仅使用非循环路径,因此可以使用顶点集的列表来表示“used”。 - Zetav.predecessor[] := u
将 predecessor
列表设置为 u
和仅 u
,而 v.predecessor += u
则将其添加到列表中。这种表示法在 https://en.wikipedia.org/w/index.php?title=Bellman%E2%80%93Ford_algorithm&oldid=500771237 中有所体现。 - Zetau.distance
或者 v.distance
可能都是无穷大(你将距离初始化为无穷大),在这种情况下,如果 u.distance + uv.weight == v.distance
对于图的非连接部分成立,那么你将得到垃圾数据。因此,在该条件中,你应该检查它们中的一个是否不是无穷大。 - Mitaru.distance
是否为 INFINITY
,这应该足够了。 - Zeta