Source code for titan_pylib.graph.flow.max_flow_dinic

 1from collections import deque
 2from titan_pylib.others.antirec import antirec
 3
 4
[docs] 5class MaxFlowDinic: 6 """mf.G[v]:= [x, cap, ind, flow]""" 7 8 def __init__(self, n: int): 9 self.n: int = n 10 self.G: list[list[list[int]]] = [[] for _ in range(n)] 11 self.level = [-1] * n 12
[docs] 13 def add_edge(self, u: int, v: int, w: int) -> None: 14 assert ( 15 0 <= u < self.n 16 ), f"Indexerror: {self.__class__.__name__}.add_edge({u}, {v})" 17 assert ( 18 0 <= v < self.n 19 ), f"Indexerror: {self.__class__.__name__}.add_edge({u}, {v})" 20 G_u = len(self.G[u]) 21 G_v = len(self.G[v]) 22 self.G[u].append([v, w, G_v, 0]) 23 self.G[v].append([u, 0, G_u, 0])
24 25 def _bfs(self, s: int) -> None: 26 level = self.level 27 for i in range(len(level)): 28 level[i] = -1 29 dq = deque([s]) 30 level[s] = 0 31 while dq: 32 v = dq.popleft() 33 for x, w, _, _ in self.G[v]: 34 if w > 0 and level[x] == -1: 35 level[x] = level[v] + 1 36 dq.append(x) 37 self.level = level 38 39 @antirec 40 def _dfs(self, v: int, g: int, f: int): 41 if v == g: 42 yield f 43 else: 44 for i in range(self.it[v], len(self.G[v])): 45 self.it[v] += 1 46 x, w, rev, _ = self.G[v][i] 47 if w > 0 and self.level[v] < self.level[x]: 48 fv = yield self._dfs(x, g, min(f, w)) 49 if fv > 0: 50 self.G[v][i][3] += f 51 self.G[x][rev][3] -= f 52 self.G[v][i][1] -= fv 53 self.G[x][rev][1] += fv 54 yield fv 55 break 56 else: 57 yield 0 58
[docs] 59 def max_flow(self, s: int, g: int, INF: int = 10**18) -> int: 60 """:math:`O(V^2 E)`""" 61 assert ( 62 0 <= s < self.n 63 ), f"Indexerror: {self.__class__.__class__}.max_flow(), {s=}" 64 assert ( 65 0 <= g < self.n 66 ), f"Indexerror: {self.__class__.__class__}.max_flow(), {g=}" 67 ans = 0 68 while True: 69 self._bfs(s) 70 if self.level[g] < 0: 71 break 72 self.it = [0] * self.n 73 while True: 74 f = self._dfs(s, g, INF) 75 if f == 0: 76 break 77 ans += f 78 return ans