Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 82afc61

Browse files
authoredOct 15, 2024··
Create Johnson’s Algorithm
1 parent 03a4251 commit 82afc61

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed
 
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import sys
2+
from collections import defaultdict
3+
4+
class Graph:
5+
def __init__(self, vertices):
6+
self.V = vertices
7+
self.graph = defaultdict(list)
8+
9+
def add_edge(self, u, v, w):
10+
self.graph[u].append((v, w))
11+
12+
def bellman_ford(self, src):
13+
dist = {v: float('inf') for v in range(self.V)}
14+
dist[src] = 0
15+
16+
for _ in range(self.V - 1):
17+
for u in range(self.V):
18+
for v, w in self.graph[u]:
19+
if dist[u] + w < dist[v]:
20+
dist[v] = dist[u] + w
21+
22+
# Check for negative-weight cycles
23+
for u in range(self.V):
24+
for v, w in self.graph[u]:
25+
if dist[u] + w < dist[v]:
26+
raise ValueError("Graph contains a negative weight cycle")
27+
28+
return dist
29+
30+
def dijkstra(self, src, h):
31+
dist = {v: float('inf') for v in range(self.V)}
32+
dist[src] = 0
33+
pq = [(0, src)]
34+
35+
while pq:
36+
d, u = heapq.heappop(pq)
37+
if d > dist[u]:
38+
continue
39+
40+
for v, w in self.graph[u]:
41+
weight = w + h[u] - h[v]
42+
if dist[u] + weight < dist[v]:
43+
dist[v] = dist[u] + weight
44+
heapq.heappush(pq, (dist[v], v))
45+
46+
return dist
47+
48+
def johnson(self):
49+
# Step 1: Add a new vertex 'q'
50+
for u in range(self.V):
51+
self.graph[self.V].append((u, 0))
52+
53+
# Step 2: Run Bellman-Ford from vertex 'q'
54+
h = self.bellman_ford(self.V)
55+
56+
# Step 3: Remove vertex 'q'
57+
del self.graph[self.V]
58+
59+
# Step 4: Reweight the edges
60+
for u in range(self.V):
61+
for index in range(len(self.graph[u])):
62+
v, w = self.graph[u][index]
63+
self.graph[u][index] = (v, w + h[u] - h[v])
64+
65+
# Step 5: Run Dijkstra for each vertex
66+
all_pairs_distances = {}
67+
for u in range(self.V):
68+
all_pairs_distances[u] = self.dijkstra(u, h)
69+
70+
return all_pairs_distances
71+
72+
import heapq
73+
74+
# Example usage
75+
if __name__ == "__main__":
76+
g = Graph(5)
77+
g.add_edge(0, 1, -1)
78+
g.add_edge(0, 2, 4)
79+
g.add_edge(1, 2, 3)
80+
g.add_edge(1, 3, 2)
81+
g.add_edge(1, 4, 2)
82+
g.add_edge(3, 1, 1)
83+
g.add_edge(3, 4, 5)
84+
g.add_edge(4, 3, -3)
85+
86+
try:
87+
distances = g.johnson()
88+
print("All pairs shortest path distances:")
89+
for u in distances:
90+
print(f"From vertex {u}: {distances[u]}")
91+
except ValueError as e:
92+
print(e)

0 commit comments

Comments
 (0)
Please sign in to comment.