Skip to content

Commit e9eb5f8

Browse files
committed
Optimize BFS and fix min-cut detection
1 parent 791deb4 commit e9eb5f8

1 file changed

Lines changed: 37 additions & 19 deletions

File tree

networking_flow/minimum_cut.py

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Minimum cut on Ford_Fulkerson algorithm.
22

3+
from collections import deque
4+
35
test_graph = [
46
[0, 16, 13, 0, 0, 0],
57
[0, 0, 10, 12, 0, 0],
@@ -11,56 +13,72 @@
1113

1214

1315
def bfs(graph, s, t, parent):
14-
# Return True if there is node that has not iterated.
1516
visited = [False] * len(graph)
16-
queue = [s]
17+
queue = deque([s])
1718
visited[s] = True
1819

1920
while queue:
20-
u = queue.pop(0)
21+
u = queue.popleft()
22+
2123
for ind in range(len(graph[u])):
22-
if visited[ind] is False and graph[u][ind] > 0:
24+
if not visited[ind] and graph[u][ind] > 0:
2325
queue.append(ind)
2426
visited[ind] = True
2527
parent[ind] = u
2628

29+
# Early exit if sink is found
30+
if ind == t:
31+
return True
32+
2733
return visited[t]
2834

2935

36+
def dfs(graph, s, visited):
37+
visited[s] = True
38+
for i in range(len(graph)):
39+
if graph[s][i] > 0 and not visited[i]:
40+
dfs(graph, i, visited)
41+
42+
3043
def mincut(graph, source, sink):
31-
"""This array is filled by BFS and to store path
44+
"""
45+
Returns max_flow and minimum cut edges.
46+
3247
>>> mincut(test_graph, source=0, sink=5)
33-
[(1, 3), (4, 3), (4, 5)]
48+
(23, [(1, 3), (4, 3), (4, 5)])
3449
"""
35-
parent = [-1] * (len(graph))
50+
residual = [i[:] for i in graph]
51+
parent = [-1] * len(graph)
3652
max_flow = 0
37-
res = []
38-
temp = [i[:] for i in graph] # Record original cut, copy.
39-
while bfs(graph, source, sink, parent):
53+
54+
while bfs(residual, source, sink, parent):
4055
path_flow = float("Inf")
4156
s = sink
4257

4358
while s != source:
44-
# Find the minimum value in select path
45-
path_flow = min(path_flow, graph[parent[s]][s])
59+
path_flow = min(path_flow, residual[parent[s]][s])
4660
s = parent[s]
4761

4862
max_flow += path_flow
49-
v = sink
5063

64+
v = sink
5165
while v != source:
5266
u = parent[v]
53-
graph[u][v] -= path_flow
54-
graph[v][u] += path_flow
67+
residual[u][v] -= path_flow
68+
residual[v][u] += path_flow
5569
v = parent[v]
5670

71+
visited = [False] * len(graph)
72+
dfs(residual, source, visited)
73+
74+
res = []
5775
for i in range(len(graph)):
58-
for j in range(len(graph[0])):
59-
if graph[i][j] == 0 and temp[i][j] > 0:
76+
for j in range(len(graph)):
77+
if visited[i] and not visited[j] and graph[i][j] > 0:
6078
res.append((i, j))
6179

62-
return res
80+
return max_flow, res
6381

6482

6583
if __name__ == "__main__":
66-
print(mincut(test_graph, source=0, sink=5))
84+
print(mincut(test_graph, source=0, sink=5))

0 commit comments

Comments
 (0)