python
from collections import defaultdict, deque
def edmonds_karp(edges, source, sink):
"""
edges: [(u, v, capacity), ...]
返回: (最大流值, 最小割的源点侧节点集合)
"""
residual = defaultdict(lambda: defaultdict(int))
graph = defaultdict(set)
for u, v, cap in edges:
if cap < 0:
raise ValueError("容量不能为负")
residual[u][v] += cap
graph[u].add(v)
graph[v].add(u)
max_flow = 0
while True:
parent = {source: None}
queue = deque([source])
while queue and sink not in parent:
u = queue.popleft()
for v in sorted(graph[u]):
if v in parent:
continue
if residual[u][v] <= 0:
continue
parent[v] = u
queue.append(v)
if sink not in parent:
break
delta = float("inf")
v = sink
while v != source:
u = parent[v]
delta = min(delta, residual[u][v])
v = u
v = sink
while v != source:
u = parent[v]
residual[u][v] -= delta
residual[v][u] += delta
v = u
max_flow += delta
reachable = {source}
queue = deque([source])
while queue:
u = queue.popleft()
for v in graph[u]:
if v not in reachable and residual[u][v] > 0:
reachable.add(v)
queue.append(v)
return max_flow, reachable
edges = [
("S", "A", 3),
("S", "B", 2),
("A", "B", 2),
("A", "T", 2),
("B", "T", 3),
]
flow, source_side = edmonds_karp(
edges, "S", "T"
)
cut_capacity = sum(
cap
for u, v, cap in edges
if u in source_side and v not in source_side
)
print("最大流:", flow)
print("最小割容量:", cut_capacity)
print("最小割源点侧:", sorted(source_side))
assert flow == cut_capacity