最大流问题:
源点source(S点)开始源源不断的通过中间的一些管道流到槽点sink(T点),求最后T点最大有多少流量。
常用的算法是增广路算法,通过不同的找增广路的方法会有不一样的复杂度,也分别为不同叫法,一般用DFS找增广路的算法叫 FF(Ford-Fulkerson)算法,用BFS的叫EK(Edmonds-Karp)算法。这里我主要记录一下EK算法。
一些概念
增广路: 这里网络流的增广路网络上的意思是指这条路径上的流可以修改,通过修改,使得整个网络的流值增大。。我的理解是可以从源点走到终点的一条路。
瓶颈: 增广路里面最小容量的边。
最大流的增广路算法步骤:
首先建立有向图,给每条有向边再建立一条反边。设mf(maximum flow)为最大流。
影响算法复杂度的主要因素是找增广路的步骤。其他改进找增广路的方法的算法有Dinic算法,Capacity-Scaling算法。
# EK算法
# 广搜寻找增广路
def bfs(start, end, graph):
q = [[start, 9999999, [start]]]
vis = [False] * len(graph)
vis[start] = True
while q:
nd, f, path = q.pop(0)
if nd == end:
return f, path
for v, c in enumerate(graph[nd]):
pa = path[:]
if c > 0 and not vis[v]:
pa.append(v)
q.append([v, min(f, c), pa])
vis[v] = True
return False
def max_flow(start, end, graph):
mf = 0
while True:
# 找增广路以及瓶颈流
result = bfs(start, end, graph)
# 当找不到增广路时算法停止,得到最大流
if result:
f, aug_path = result
# 更新增广路的正负边的权值
for i in range(len(aug_path) - 1):
u, v = aug_path[i], aug_path[i + 1]
graph[u][v] -= f
graph[v][u] += f
# 最大流总数加上瓶颈流
mf += f
else:
return mf
edges = [
[4, 0, 10],
[4, 1, 10],
[0, 2, 25],
[1, 3, 15],
[3, 0, 6],
[2, 5, 10],
[3, 5, 10]
]
n = 6
# 源点与汇点
from_node, to_node = 4, 5
# directed graph
# 邻接矩阵
graph = [[0] * n for _ in range(n)]
# 构图:邻接表
for u, v, c in edges:
# 有重边的加等,不能重边的直接赋值
graph[u][v] += c
# graph[u][v] = c
print(max_flow(from_node, to_node, graph))