diff --git a/networking_flow/minimum_cut.py b/networking_flow/minimum_cut.py index 164b45f1012a..1124ad2be21c 100644 --- a/networking_flow/minimum_cut.py +++ b/networking_flow/minimum_cut.py @@ -1,5 +1,7 @@ # Minimum cut on Ford_Fulkerson algorithm. +from collections import deque + test_graph = [ [0, 16, 13, 0, 0, 0], [0, 0, 10, 12, 0, 0], @@ -11,55 +13,71 @@ def bfs(graph, s, t, parent): - # Return True if there is node that has not iterated. visited = [False] * len(graph) - queue = [s] + queue = deque([s]) visited[s] = True while queue: - u = queue.pop(0) + u = queue.popleft() + for ind in range(len(graph[u])): - if visited[ind] is False and graph[u][ind] > 0: + if not visited[ind] and graph[u][ind] > 0: queue.append(ind) visited[ind] = True parent[ind] = u + # Early exit if sink is found + if ind == t: + return True + return visited[t] +def dfs(graph, s, visited): + visited[s] = True + for i in range(len(graph)): + if graph[s][i] > 0 and not visited[i]: + dfs(graph, i, visited) + + def mincut(graph, source, sink): - """This array is filled by BFS and to store path + """ + Returns max_flow and minimum cut edges. + >>> mincut(test_graph, source=0, sink=5) - [(1, 3), (4, 3), (4, 5)] + (23, [(1, 3), (4, 3), (4, 5)]) """ - parent = [-1] * (len(graph)) + residual = [i[:] for i in graph] + parent = [-1] * len(graph) max_flow = 0 - res = [] - temp = [i[:] for i in graph] # Record original cut, copy. - while bfs(graph, source, sink, parent): + + while bfs(residual, source, sink, parent): path_flow = float("Inf") s = sink while s != source: - # Find the minimum value in select path - path_flow = min(path_flow, graph[parent[s]][s]) + path_flow = min(path_flow, residual[parent[s]][s]) s = parent[s] max_flow += path_flow - v = sink + v = sink while v != source: u = parent[v] - graph[u][v] -= path_flow - graph[v][u] += path_flow + residual[u][v] -= path_flow + residual[v][u] += path_flow v = parent[v] + visited = [False] * len(graph) + dfs(residual, source, visited) + + res = [] for i in range(len(graph)): - for j in range(len(graph[0])): - if graph[i][j] == 0 and temp[i][j] > 0: + for j in range(len(graph)): + if visited[i] and not visited[j] and graph[i][j] > 0: res.append((i, j)) - return res + return max_flow, res if __name__ == "__main__":