Johnson’s Algorithm is an algorithm that computes the length of the shortest path between every pair of vertices in a directed graph with edge weights and no negative cycles in
-
time and space, or
-
time and space.
Tip
This problem can also be solved by the Floyd-Warshall Algorithm in time and space.
Tip
This problem can also be solved by the Bellman-Ford Algorithm in time and space.
Algorithm
Let denote the length of the shortest path between and in graph .
-
Let be a new vertex, and let .
-
Apply the Bellman-Ford Algorithm to find for each vertex in .
Lemma
Let , then
Proof
- If , since it follows that, let be a shortest path from to , then is a path from to with a weight less than .
By contradiction, it follows that .
- Let , then applying the lemma yields that is a directed graph with non-negative edge weights.
- Apply Dijkstra’s Algorithm times to find for each pair of vertices and in .
Lemma
Proof
Let be a path from to in , be the corresponding path in .
- Apply the lemma to find .
This algorithm solves the problem in
-
time and space, or
-
time and space.
std::vector<std::vector<int>> johnson(int n, int m, std::vector<int> u, std::vector<int> v, std::vector<int> w) {
for (int i = 0; i < n; i++) {
u.push_back(n);
v.push_back(i);
w.push_back(0);
}
auto h = bellman_ford(n, m, u, v, w, n);
for (int i = 0; i < m; i++) {
w[i] += h[u[i]] - h[v[i]];
}
std::vector dist(n, std::vector<int>(n));
for (int i = 0; i < n; i++) {
dist[i] = dijkstra(n, m, u, v, w, i);
for (int j = 0; j < n; j++) {
dist[i][j] -= h[i] - h[j];
}
}
return dist;
}