I've implemented Floyd-Warshall to return the distance of the shortest path between every pair of nodes/vertices and a single shortest path between each of these pairs.
Is there any way to get it to return every shortest path, even when there are multiple paths that are tied for shortest, for every pair of nodes? (I just want to know if I'm wasting my time trying)
Unlike Dijkstra's algorithm, Floyd Warshall can be implemented in a distributed system, making it suitable for data structures such as Graph of Graphs (Used in Maps). Lastly Floyd Warshall works for negative edge but no negative cycle, whereas Dijkstra's algorithm don't work for negative edges.
Floyd Warshall's all pairs shortest paths algorithm works for graphs with negative edge weights because the correctness of the algorithm does not depend on edge's weight being non-negative, while the correctness of Dijkstra's algorithm is based on this fact.
Floyd-Warshall algorithm It is used to find all pair shortest path problem from a given weighted graph.
If you just need the count of how many different shortest path exist, you can keep a count
array in addition to the shortestPath
array. Here's is a quick modification of the pseudocode from wiki.
procedure FloydWarshall ()
for k := 1 to n
for i := 1 to n
for j := 1 to n
if path[i][j] == path[i][k]+path[k][j] and k != j and k != i
count[i][j] += 1;
else if path[i][j] > path[i][k] + path[k][j]
path[i][j] = path[i][k] + path[k][j]
count[i][j] = 1
If you need a way to find all the paths, you can store a vector/arraylist
like structure for each pair to expand and collapse. Here is a modification of the pseudocode from the same wiki.
procedure FloydWarshallWithPathReconstruction ()
for k := 1 to n
for i := 1 to n
for j := 1 to n
if path[i][k] + path[k][j] < path[i][j]
path[i][j] := path[i][k]+path[k][j];
next[i][j].clear()
next[i][j].push_back(k) // assuming its a c++ vector
else if path[i][k] + path[k][j] == path[i][j] and path[i][j] != MAX_VALUE and k != j and k != i
next[i][j].push_back(k)
Note: if k==j
or k==i
, that means, you're checking either path[i][i]+path[i][j]
or path[i][j]+path[j][j]
, both should be equal to path[i][j]
and that does not get pushed into next[i][j]
.
Path reconstruction should be modified to handle the vector
. The count in this case would be each vector
's size. Here is a modification of the pseudocode (python) from the same wiki.
procedure GetPath(i, j):
allPaths = empty 2d array
if next[i][j] is not empty:
for every k in next[i][j]:
if k == -1: // add the path = [i, j]
allPaths.add( array[ i, j] )
else: // add the path = [i .. k .. j]
paths_I_K = GetPath(i,k) // get all paths from i to k
paths_K_J = GetPath(k,j) // get all paths from k to j
for every path between i and k, i_k in paths_I_K:
for every path between k and j, k_j in paths_K_J:
i_k = i_k.popk() // remove the last element since that repeats in k_j
allPaths.add( array( i_k + j_k) )
return allPaths
Note: path[i][j]
is an adjacency list. While initializing path[i][j]
, you can also initialize next[i][j]
by adding a -1
to the array. For instance an initialization of next[i][j]
would be
for every edge (i,j) in graph:
next[i][j].push_back(-1)
This takes care of an edge being the shortest path itself. You'll have to handle this special case in the path reconstruction, which is what i'm doing in GetPath
.
Edit: "MAX_VALUE" is the initialized value in the array of distances.
The 'counting' function in the current approved answer flails in some cases. A more complete solution would be:
procedure FloydWarshallWithCount ()
for k := 1 to n
for i := 1 to n
for j := 1 to n
if path[i][j] == path[i][k]+path[k][j]
count[i][j] += count[i][k] * count[k][j]
else if path[i][j] > path[i][k] + path[k][j]
path[i][j] = path[i][k] + path[k][j]
count[i][j] = count[i][k] * count[k][j]
The reason for this is that for any three vertices i, j, and k, there may be multiple shortest paths that run from i through k to j. For instance in the graph:
3 1
(i) -------> (k) ---------> (j)
| ^
| |
| 1 | 1
| 1 |
(a) -------> (b)
Where there are two paths from i to j through k. count[i][k] * count[k][j]
finds the number of paths from i to k, and the number of paths from k to j, and multiplies them to find the number of paths i -> k -> j.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With