Source code for titan_pylib.graph.flow.max_flow_ford_fulkerson
1import sys
2
3
[docs]
4class MaxFlowFordFulkerson:
5
6 def __init__(self, n: int):
7 self.n: int = n
8 self.m: int = 0
9 self.G: list[list[list[int]]] = [[] for _ in range(n)]
10
[docs]
11 def add_edge(self, u: int, v: int, w: int) -> None:
12 assert (
13 0 <= u < self.n
14 ), f"Indexerror: {self.__class__.__name__}.add_edge({u}, {v})"
15 assert (
16 0 <= v < self.n
17 ), f"Indexerror: {self.__class__.__name__}.add_edge({u}, {v})"
18 G_u = len(self.G[u])
19 G_v = len(self.G[v])
20 self.G[u].append([v, w, G_v])
21 self.G[v].append([u, 0, G_u])
22 self.m += 2
23
24 def _dfs(self, v: int, g: int, f: int, used: list[int]) -> int:
25 if v == g:
26 return f
27 used[v] = 1
28 for i, (x, w, l) in enumerate(self.G[v]):
29 if used[x]:
30 continue
31 if w == 0:
32 continue
33 fv = self._dfs(x, g, min(f, w), used)
34 if fv > 0:
35 self.G[v][i][1] -= fv
36 self.G[x][l][1] += fv
37 return fv
38 return 0
39
[docs]
40 def max_flow(self, s: int, g: int, INF: int = 10**18) -> int:
41 """:math:`O(F|E|)"""
42 assert (
43 0 <= s < self.n
44 ), f"Indexerror: {self.__class__.__class__}.max_flow(), {s=}"
45 assert (
46 0 <= g < self.n
47 ), f"Indexerror: {self.__class__.__class__}.max_flow(), {g=}"
48 lim_rec = sys.getrecursionlimit()
49 if lim_rec < self.m:
50 sys.setrecursionlimit(self.m + 1)
51 ans = 0
52 while True:
53 used = [0] * self.n
54 f = self._dfs(s, g, INF, used)
55 if f == 0:
56 break
57 ans += f
58 return ans