@@ -76,3 +76,55 @@ def _initialize_single_source(
7676 distance [node ] = float ("inf" )
7777 predecessor [node ] = None
7878 distance [source ] = 0
79+
80+
81+
82+ def bellman_ford_paths (
83+ graph : dict [str , dict [str , float ]], source : str
84+ ) -> tuple [dict [str , float ] | None , dict [str , str | None ] | None , bool ]:
85+ """Compute shortest-path distances and predecessors via Bellman-Ford."""
86+ distance : dict [str , float ] = {}
87+ predecessor : dict [str , str | None ] = {}
88+
89+ _initialize_single_source (graph , source , distance , predecessor )
90+
91+ num_vertices = len (graph )
92+ for _ in range (1 , num_vertices ):
93+ for current_node in graph :
94+ if distance [current_node ] == float ("inf" ):
95+ continue
96+ for neighbor , edge_weight in graph [current_node ].items ():
97+ if distance [neighbor ] > distance [current_node ] + edge_weight :
98+ distance [neighbor ] = distance [current_node ] + edge_weight
99+ predecessor [neighbor ] = current_node
100+
101+ for current_node in graph :
102+ if distance [current_node ] == float ("inf" ):
103+ continue
104+ for neighbor , edge_weight in graph [current_node ].items ():
105+ if distance [neighbor ] > distance [current_node ] + edge_weight :
106+ return None , None , True
107+
108+ return distance , predecessor , False
109+
110+
111+ def reconstruct_shortest_path (
112+ predecessor : dict [str , str | None ], source : str , target : str
113+ ) -> list [str ]:
114+ """Rebuild the shortest path from *source* to *target*."""
115+ path : list [str ] = []
116+ visited : set [str ] = set ()
117+ node : str | None = target
118+
119+ while node is not None and node not in visited :
120+ visited .add (node )
121+ path .append (node )
122+ if node == source :
123+ break
124+ node = predecessor .get (node )
125+
126+ if not path or path [- 1 ] != source :
127+ return []
128+
129+ path .reverse ()
130+ return path
0 commit comments