我正在尝试研究 this 博文中的 google foobar 问题。 (问题如下所述。)
作者在博客中发布了他的代码,并声称它已通过 Dinic's algorithm 解决。
我在相关的维基百科页面上阅读了 Dinic 的算法并观看了 YouTube video。我发现代码(附在下面)的文档很差,我没有找到算法是如何在代码中实现的线索。尤其是看不到“层级图”和“阻塞流”是在哪里构造的。
谁能看到函数 bfs()
中的大 while 循环在做什么?
给定兔子组的起始房间号、逃生舱的房间号以及中间每个走廊的每个方向一次可以通过的兔子数量,计算出可以安全通过的兔子数量在高峰期一次到逃生舱。
编写一个函数 answer(entrances, exits, path) ,它采用一个整数数组表示聚集的兔子组在哪里,一个整数数组表示逃生舱所在的位置,以及一个整数数组数组走廊,以整数形式返回每个时间步可以通过的兔子总数。入口和出口是不相交的,因此永远不会重叠。路径元素 path[A][B] = C 描述了从 A 到 B 的走廊在每个时间步都可以容纳 C 个兔子。最多有 50 个房间由走廊连接,最多可以容纳 200 万只兔子。
例如,如果您有:
entrances = [0, 1]
exits = [4, 5]
path = [ [0, 0, 4, 6, 0, 0], # Room 0: Bunnies
[0, 0, 5, 2, 0, 0], # Room 1: Bunnies
[0, 0, 0, 0, 4, 4], # Room 2: Intermediate room
[0, 0, 0, 0, 6, 6], # Room 3: Intermediate room
[0, 0, 0, 0, 0, 0], # Room 4: Escape pods
[0, 0, 0, 0, 0, 0], # Room 5: Escape pods ]
然后在每个时间步中,可能会发生以下情况:
0 sends 4/4 bunnies to 2 and 6/6 bunnies to 3
1 sends 4/5 bunnies to 2 and 2/2 bunnies to 3
2 sends 4/4 bunnies to 4 and 4/4 bunnies to 5
3 sends 4/6 bunnies to 4 and 4/6 bunnies to 5
因此,在每个时间步长 4 和 5 时,总共有 16 只兔子可以到达逃生舱。 (请注意,在此示例中,房间 3 可以将 8 只兔子的任何变体发送给 4 和 5,例如 2/6 和 6/6,但最终答案保持不变。)
def bfs(matrix, source, destination):
visited = [-1 for i in range(len(matrix))]
visited[source] = source
queue = [source]
while len(queue) > 0:
top = queue.pop(0)
for i in range(len(matrix)):
if (matrix[top][i][1] - matrix[top][i][0]) != 0 and visited[i] == -1:
if i == destination:
# Get route
visited[destination] = top
path = [destination]
temp = destination
while temp != source:
temp = visited[temp]
path.append(temp)
path.reverse()
# Get flow value and update augmented graph
temp = 1
total = float("inf")
cur = source
while temp != len(path):
entry = matrix[cur][path[temp]]
diff = abs(entry[1]) - entry[0]
total = min(total, diff)
cur = path[temp]
temp += 1
temp = 1
cur = source
while temp != len(path):
entry = matrix[cur][path[temp]]
if entry[1] < 0: # Already augmented need to flip
entry[1] += total
else:
entry[0] += total
entry = matrix[path[temp]][cur]
if entry[1] <= 0: # Already augmented need to flip
entry[1] -= total
else:
entry[0] += total
cur = path[temp]
temp += 1
return True
else:
visited[i] = top
queue.append(i)
return False
def answer(entrances, exits, path):
max_val = sum(list(map(sum, path)))
aug = []
for i in range(len(path)):
aug.append([])
for j in range(len(path[i])):
aug[i].append([0, path[i][j]])
aug[i].append([0, 0])
if i in exits:
aug[i].append([0, max_val])
else:
aug[i].append([0, 0])
aug.append([])
aug.append([])
for i in range(len(path[0]) + 2):
if i in entrances:
aug[-2].append([0, max_val])
else:
aug[-2].append([0, 0])
aug[-1].append([0, 0])
while bfs(aug, len(aug)-2, len(aug)-1):
pass
total = 0
for i in range(len(aug)):
total += aug[-2][i][0]
return total