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 the
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.