|
| 1 | +from collections import deque |
| 2 | +from typing import List, Tuple |
| 3 | + |
| 4 | +class MinCostMaxFlow: |
| 5 | + def __init__(self, n: int): |
| 6 | + self.n = n |
| 7 | + self.graph = [[] for _ in range(n)] |
| 8 | + |
| 9 | + def add_edge(self, u: int, v: int, capacity: int, cost: int): |
| 10 | + self.graph[u].append([v, capacity, cost, len(self.graph[v])]) |
| 11 | + self.graph[v].append([u, 0, -cost, len(self.graph[u]) - 1]) |
| 12 | + |
| 13 | + def bellman_ford(self, source: int, dist: List[int], parent: List[Tuple[int, int]]): |
| 14 | + dist[:] = [float('inf')] * self.n |
| 15 | + dist[source] = 0 |
| 16 | + in_queue = [False] * self.n |
| 17 | + queue = deque([source]) |
| 18 | + in_queue[source] = True |
| 19 | + |
| 20 | + while queue: |
| 21 | + u = queue.popleft() |
| 22 | + in_queue[u] = False |
| 23 | + for i, (v, capacity, cost, rev) in enumerate(self.graph[u]): |
| 24 | + if capacity > 0 and dist[u] + cost < dist[v]: |
| 25 | + dist[v] = dist[u] + cost |
| 26 | + parent[v] = (u, i) |
| 27 | + if not in_queue[v]: |
| 28 | + queue.append(v) |
| 29 | + in_queue[v] = True |
| 30 | + |
| 31 | + def min_cost_max_flow(self, source: int, sink: int) -> Tuple[int, int]: |
| 32 | + flow = 0 |
| 33 | + cost = 0 |
| 34 | + dist = [0] * self.n |
| 35 | + parent = [(-1, -1)] * self.n |
| 36 | + |
| 37 | + while True: |
| 38 | + self.bellman_ford(source, dist, parent) |
| 39 | + if dist[sink] == float('inf'): |
| 40 | + break |
| 41 | + |
| 42 | + path_flow = float('inf') |
| 43 | + v = sink |
| 44 | + while v != source: |
| 45 | + u, i = parent[v] |
| 46 | + path_flow = min(path_flow, self.graph[u][i][1]) |
| 47 | + v = u |
| 48 | + |
| 49 | + flow += path_flow |
| 50 | + cost += path_flow * dist[sink] |
| 51 | + |
| 52 | + v = sink |
| 53 | + while v != source: |
| 54 | + u, i = parent[v] |
| 55 | + self.graph[u][i][1] -= path_flow |
| 56 | + rev = self.graph[u][i][3] |
| 57 | + self.graph[v][rev][1] += path_flow |
| 58 | + v = u |
| 59 | + |
| 60 | + return flow, cost |
0 commit comments