I've successfully implemented Bellman-Ford to find the distance of the shortest path when edges have negative weights/distances. I've not been able to get it to return all shortest paths (when there are ties for shortest). I managed to get all shortest paths (between a given pair of nodes) with Dijkstra. Is this possible with Bellman-Ford? (just want to know if I'm wasting my time trying)
Asked
Active
Viewed 7,394 times
6

templatetypedef
- 362,284
- 104
- 897
- 1,065

user1507844
- 5,973
- 10
- 38
- 55
-
Mathematically, I'm not sure this is possible. If all of the edges have cost zero, for example, there are infinitely many possible shortest paths that you can take. Do you want shortest acyclic paths? – templatetypedef Jul 06 '12 at 21:48
-
Yes, sorry, should have specified that. I'd like to find all shortest acyclic paths between two nodes. – user1507844 Jul 06 '12 at 21:58
1 Answers
9
If you alter the second step of the Bellman-Ford algorithm a little bit you can achieve something very similar:
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
where v.predecessor
is a list of vertices. If the new distance of v
equals a path which isn't included yet include the new predecessor.
In order to print all shortest paths you could use something like
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)
Use printPaths(stop,start,stop,stop.id)
in order to print all paths.
Note: It is possible to exclude if u not in v.predecessor then v.predecessor += u
from the modified algorithm if you remove duplicate elements after the algorithm has finished.

Zeta
- 103,620
- 13
- 194
- 236
-
Thank you that was very helpful. I actually had managed to to do everything except the recursive printPaths procedure, which is really quite simple after looking at it. Is there a way to print all the paths without recursion? In a more general sense, is it always possible to use a loop instead of recursion? – user1507844 Jul 07 '12 at 11:05
-
Yes, but it's tricky to keep track of `used` since this is a backtracking algorithm. If you want to create a iterative version you would have to manipulate the `used` list somehow without creating a infinite loop. There are some crude solutions, for example build a `queue[0,...,n-1]`, where `queue[i]` contains all possible predecessors of the `i` level (`queue[0] := [stop]`) and use a n-dimensional multiindex `I` to iterate over the queue. But you would have to check whether the current set `I` is valid. Since you're only using acyclic paths you can then use a list of vertex sets for `used`. – Zeta Jul 07 '12 at 12:50
-
what is the difference between v.predecessor[] := u and v.predecessor += u ? – calibr Nov 30 '19 at 11:24
-
1@calibr `v.predecessor[] := u` sets the list of `predecessor` to `u` and just `u`, whereas `v.predecessor += u` adds it to the list. The notation was somewhat taken from https://en.wikipedia.org/w/index.php?title=Bellman%E2%80%93Ford_algorithm&oldid=500771237. – Zeta Dec 01 '19 at 22:38
-
I would suggest another check: `u.distance` or `v.distance` might both be infinity (you initialize distances to infinity) and in that case `u.distance + uv.weight == v.distance` will be true for not-connected parts of a graph and you will get garbage. So you should check that one of them is not infinity in that if condition. – Mitar Aug 15 '23 at 09:56
-
@Mitar Good point. I've added a check whether `u.distance` is `INFINITY`, which should be enough. – Zeta Aug 21 '23 at 10:59