📅  最后修改于: 2023-12-03 14:58:37.288000             🧑  作者: Mango
本题目是“门|门”是校内著名的游乐项目。在游玩过程中,游客访问了若干门(有可能是同一个门),最终达到了目的地。现在我们知道游客走过的所有门及目的地,现在我们需要求出至少需要造多少个新门,使得所有游客只要走这些门就可以直达目的地。
本题目的输入是以邻接表形式给出密集图,其中点的个数不超过1000,边数不超过100000。输出至少需造几个门才能满足条件。
本题目需要进行网络最大流问题的求解。我们可以将每个门拆成入门和出门两个节点,并在这两个节点之间连一条容量为1的边。同时,在入门节点和出门节点之间也连一条容量为1的边。对于原图中的每一条边(u, v),从出门节点u的出度向入门节点v的入度连一条容量为1的边。对于游客在起点和终点处的门,我们也将其拆成对应的入门和出门节点,并在其对应的入门和出门节点之间连一条容量为1的边。最后,从源点向所有起点的入门节点连一条容量为1的边;从所有终点的出门节点向汇点连一条容量为1的边。利用最大流算法,求解拆分后的网络中,从源点到汇点的最大流即可得到答案。
以下是该问题的代码实现,其中 networkFlow
为本题目最大流问题的解法。
from typing import List, Tuple
def min_door_num(edges: List[Tuple[int, int]], s: int, t: int) -> int:
"""求最少需要造多少个新门才能满足条件
:param edges: 边列表,其中每个元素为两个节点编号,表示一条边
:param s: 起点编号
:param t: 终点编号
:returns: 最少需要造多少个新门
"""
# 构建最大流网络
n = max(max(x) for x in edges) + 2
graph = [[0 for _ in range(n)] for _ in range(n)]
for u, v in edges:
u_in, u_out = u * 2, u * 2 + 1
v_in, v_out = v * 2, v * 2 + 1
graph[u_out][v_in] += 1
for i in range(n // 2):
graph[i*2][i*2+1] += 1
for i in range(s):
in_node, out_node = i * 2, i * 2 + 1
graph[n-2][in_node] += 1
for i in range(t):
in_node, out_node = i * 2, i * 2 + 1
graph[out_node][n-1] += 1
# 求最大流
return networkFlow(graph, n-2, n-1)