Skip to content

Commit 476aff0

Browse files
Update graph.py
1 parent 2e8ba81 commit 476aff0

File tree

1 file changed

+62
-31
lines changed

1 file changed

+62
-31
lines changed

graphs/bellman-ford/graph.py

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,75 @@
44
# to all other vertices in weighted graph.
55
# Runtime O(V*E)
66

7+
from typing import Set, Dict, List, Tuple
8+
9+
710
class Graph:
8-
def __init__(self):
9-
self.vertices: list = []
10-
self.edges: list = []
11-
self.distance: dict = {}
12-
self.prev: dict = {}
13-
14-
def add_vertex(self, label: str):
15-
self.vertices.append(label)
16-
self.distance[label] = None
11+
12+
13+
def __init__(self) -> None:
14+
self.vertices:Set[str] = set()
15+
self.edges:List[Tuple[str, str, int]] = list()
16+
self.prev:Dict[str, str] = dict()
17+
self.distances:Dict[str, int] = dict()
18+
19+
20+
def add_vertex(self, label:str) -> None:
21+
self.vertices.add(label)
1722
self.prev[label] = None
23+
self.distances[label] = None
1824

19-
def add_edge(self, label1: str, label2: str, weight: int):
20-
self.edges.append([label1, label2, weight])
2125

22-
def bellman_ford(self, source: str):
23-
self.distance[source] = 0
26+
def add_edge(self, v1:str, v2:str, distance:int) -> None:
27+
self.edges.append((v1, v2, distance))
2428

25-
for _ in range(len(self.vertices)):
2629

27-
for edge in self.edges:
28-
label1: str = edge[0]
29-
label2: str = edge[1]
30-
weight: int = edge[2]
30+
def bellman_ford(self, label:str) -> None:
31+
self.distances[label] = 0
3132

32-
if self.distance[label1] is None:
33-
continue
34-
if self.distance[label2] is None:
35-
self.distance[label2] = self.distance[label1] + weight
36-
self.prev[label2] = label1
37-
continue
38-
if self.distance[label1] + weight < self.distance[label2]:
39-
self.distance[label2] = self.distance[label1] + weight
40-
self.prev[label2] = label1
33+
for _ in range(len(self.vertices) - 1):
34+
35+
for v1, v2, distance in self.edges:
36+
if self.distances[v1] is None:
4137
continue
38+
if self.distances[v2] is None or self.distances[v2] > self.distances[v1] + distance:
39+
self.distances[v2] = self.distances[v1] + distance
40+
self.prev[v2] = v1
41+
42+
# Check for negative-weight cycles
43+
for v1, v2, distance in self.edges:
44+
if self.distances[v1] is not None and self.distances[v2] > self.distances[v1] + distance:
45+
raise ValueError("Graph contains a negative-weight cycle")
4246

43-
def print_distances(self, source: str):
47+
self._print_paths(label)
48+
49+
50+
def _print_paths(self, label:str) -> None:
4451
for v in self.vertices:
45-
if v != source:
46-
distance: int = self.distance[v]
47-
print(f'Distance from {source} to {v} is {distance}')
52+
if v == label:
53+
continue
54+
if self.distances[v] is not None:
55+
print(f'Path from {label} to {v} is {self._return_path(v)} and distance is {self.distances[v]}')
56+
else:
57+
print(f'No path from {label} to {v}')
58+
59+
60+
def _return_path(self, label:str) -> str:
61+
if self.prev[label] is None:
62+
return label
63+
return self._return_path(self.prev[label]) + ' -> ' + label
64+
65+
66+
67+
g = Graph()
68+
for v in ['A', 'B', 'C', 'D']:
69+
g.add_vertex(v)
70+
71+
g.add_edge('A', 'B', 1)
72+
g.add_edge('B', 'C', 3)
73+
g.add_edge('A', 'C', 10)
74+
g.add_edge('C', 'D', 2)
75+
g.add_edge('D', 'B', 4)
76+
77+
g.bellman_ford('A')
78+

0 commit comments

Comments
 (0)