77 (2) Choose the augmenting path from source to sink and add the path to flow
88"""
99
10+ from collections import deque
11+ from typing import List
12+
1013graph = [
1114 [0 , 16 , 13 , 0 , 0 , 0 ],
1215 [0 , 0 , 10 , 12 , 0 , 0 ],
1720]
1821
1922
20- def breadth_first_search (graph : list , source : int , sink : int , parents : list ) -> bool :
23+ def breadth_first_search (graph : List [ List [ int ]] , source : int , sink : int , parents : List [ int ] ) -> bool :
2124 """
2225 This function returns True if there is a node that has not iterated.
2326
@@ -37,25 +40,31 @@ def breadth_first_search(graph: list, source: int, sink: int, parents: list) ->
3740 ...
3841 IndexError: list index out of range
3942 """
40- visited = [ False ] * len (graph ) # Mark all nodes as not visited
41- queue = [] # breadth-first search queue
42-
43- # Source node
43+ num_nodes = len (graph )
44+ visited = [False ] * num_nodes
45+ queue = deque ()
46+
4447 queue .append (source )
4548 visited [source ] = True
46-
49+
4750 while queue :
48- u = queue .pop (0 ) # Pop the front node
49- # Traverse all adjacent nodes of u
50- for ind , node in enumerate (graph [u ]):
51- if visited [ind ] is False and node > 0 :
52- queue .append (ind )
53- visited [ind ] = True
54- parents [ind ] = u
51+ current_node = queue .popleft ()
52+
53+ # If we reached the sink, we can stop early
54+ if current_node == sink :
55+ return True
56+
57+ # Check all adjacent nodes
58+ for neighbor , capacity in enumerate (graph [current_node ]):
59+ if not visited [neighbor ] and capacity > 0 :
60+ visited [neighbor ] = True
61+ parents [neighbor ] = current_node
62+ queue .append (neighbor )
63+
5564 return visited [sink ]
5665
5766
58- def ford_fulkerson (graph : list , source : int , sink : int ) -> int :
67+ def ford_fulkerson (graph : List [ List [ int ]] , source : int , sink : int ) -> int :
5968 """
6069 This function returns the maximum flow from source to sink in the given graph.
6170
@@ -80,28 +89,34 @@ def ford_fulkerson(graph: list, source: int, sink: int) -> int:
8089 >>> ford_fulkerson(test_graph, 0, 5)
8190 23
8291 """
83- # This array is filled by breadth-first search and to store path
84- parent = [- 1 ] * (len (graph ))
92+ # Create a copy of the graph to avoid modifying the original
93+ residual_graph = [row [:] for row in graph ]
94+ num_nodes = len (residual_graph )
95+ parents = [- 1 ] * num_nodes
8596 max_flow = 0
8697
87- # While there is a path from source to sink
88- while breadth_first_search (graph , source , sink , parent ):
89- path_flow = int (1e9 ) # Infinite value
90- s = sink
91-
92- while s != source :
93- # Find the minimum value in the selected path
94- path_flow = min (path_flow , graph [parent [s ]][s ])
95- s = parent [s ]
96-
98+ # Augment the flow while there is a path from source to sink
99+ while breadth_first_search (residual_graph , source , sink , parents ):
100+ # Find the minimum residual capacity along the path
101+ path_flow = float ('inf' )
102+ current_node = sink
103+
104+ # Find the minimum capacity in the path
105+ while current_node != source :
106+ parent_node = parents [current_node ]
107+ path_flow = min (path_flow , residual_graph [parent_node ][current_node ])
108+ current_node = parent_node
109+
110+ # Add path flow to overall flow
97111 max_flow += path_flow
98- v = sink
99112
100- while v != source :
101- u = parent [v ]
102- graph [u ][v ] -= path_flow
103- graph [v ][u ] += path_flow
104- v = parent [v ]
113+ # Update residual capacities of the edges and reverse edges
114+ current_node = sink
115+ while current_node != source :
116+ parent_node = parents [current_node ]
117+ residual_graph [parent_node ][current_node ] -= path_flow
118+ residual_graph [current_node ][parent_node ] += path_flow
119+ current_node = parent_node
105120
106121 return max_flow
107122
0 commit comments