44# to all other vertices in weighted graph.
55# Runtime O(V*E)
66
7+ from typing import Set , Dict , List , Tuple
8+ 9+ 710class 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