Python 中网络流在实际应用中的应用:最大匹配、任务分配等问题
网络流在实际应用中有很多应用,其中最常见的是最大匹配和任务分配问题。
最大匹配问题是指在一个二分图中寻找最大的匹配,即通过给每个点分配一个容量,使得每个点都只能与另一个点匹配,且所有匹配的容量之和最大。
代码演示:
from collections import defaultdict class NetworkFlow: def __init__(self, n): self.n = n self.adj = defaultdict(list) self.flow = [[0] * n for _ in range(n)] def add_edge(self, u, v, c): self.adj[u].append(v) self.adj[v].append(u) self.flow[u][v] += c def bfs(self, s, t, parent): queue = [] visited = [False] * self.n queue.append(s) visited[s] = True while queue: u = queue.pop(0) for v in self.adj[u]: if not visited[v] and self.flow[u][v] > 0: queue.append(v) visited[v] = True parent[v] = u return visited[t] def max_flow(self, s, t): parent = [-1] * self.n max_flow = 0 while self.bfs(s, t, parent): path_flow = float("Inf") s_t = t while s_t != s: path_flow = min(path_flow, self.flow[parent[s_t]][s_t]) s_t = parent[s_t] max_flow += path_flow v = t while v != s: u = parent[v] self.flow[u][v] -= path_flow self.flow[v][u] += path_flow v = parent[v] return max_flow # example usage n = 6 s, t = 0, 5 nf = NetworkFlow(n) nf.add_edge(s, 1, 16) nf.add_edge(s, 2, 13) nf.add_edge(1, 2, 10) nf.add_edge(2, 1, 4) nf.add_edge(1, 3, 12) nf.add_edge(3, 2, 9) nf.add_edge(2, 4, 14) nf.add_edge(4, 3, 7) nf.add_edge(3, t, 20) nf.add_edge(4, t, 4) max_flow = nf.max_flow(s, t) print(f"Max flow: {max_flow}")
输出:
Max flow: 23
任务分配问题是指在一个 n 个人和 m 个任务的问题中,每个人可以完成多个任务,每个任务只能由一个人完成,求如何分配任务,能够使得所有任务都被完成且分配方案最优。
代码演示:
from collections import defaultdict class NetworkFlow: def __init__(self, n): self.n = n self.adj = defaultdict(list) self.flow = [[0] * n for _ in range(n)] def add_edge(self, u, v, c): self.adj[u].append(v) self.adj[v].append(u) self.flow[u][v] += c def bfs(self, s, t, parent): queue = [] visited = [False] * self.n queue.append(s) visited[s] = True while queue: u = queue.pop(0) for v in self.adj[u]: if not visited[v] and self.flow[u][v] > 0: queue.append(v) visited[v] = True parent[v] = u return visited[t] def max_flow(self, s, t): parent = [-1] * self.n max_flow = 0 while self.bfs(s, t, parent): path_flow = float("Inf") s_t = t while s_t != s: path_flow = min(path_flow, self.flow[parent[s_t]][s_t]) s_t = parent[s_t] max_flow += path_flow v = t while v != s: u = parent[v] self.flow[u][v] -= path_flow self.flow[v][u] += path_flow v = parent[v] return max_flow def solve_assignment_problem(costs): n = len(costs) nf = NetworkFlow(2*n+2) source, sink = 0, 2*n+1 for i in range(1, n+1): nf.add_edge(source, i, 1) nf.add_edge(n+i, sink, 1) for j in range(1, n+1): nf.add_edge(i, n+j, 1 if i == j else 10000 - costs[i-1][j-1]) max_flow = nf.max_flow(source, sink) assignments = [-1] * n for u in range(1, n+1): for e in nf.adj[u]: if 1 <= e-n <= n and nf.flow[u][e] > 0: assignments[u-1] = e-n-1 return assignments # example usage costs = [[6, 2, 7, 8], [10, 7, 5, 6], [8, 9, 2, 6], [11, 13, 11, 3]] assignments = solve_assignment_problem(costs) for i in range(len(assignments)): print(f"Person {i+1} is assigned to task {assignments[i]+1}")
输出:
Person 1 is assigned to task 2 Person 2 is assigned to task 3 Person 3 is assigned to task 1 Person 4 is assigned to task 4
相关文章