如果有人对实现感兴趣,这里有一个push–relabel maximum flow algorithm
带有relabel-to-front
选择规则的红宝石版本。
def relabel_to_front(capacities, source, sink)
n = capacities.length
flow = Array.new(n) { Array.new(n, 0) }
height = Array.new(n, 0)
excess = Array.new(n, 0)
seen = Array.new(n, 0)
queue = (0...n).select { |i| i != source && i != sink }.to_a
height[source] = n - 1
excess[source] = Float::INFINITY
(0...n).each { |v| push(source, v, capacities, flow, excess) }
p = 0
while p < queue.length
u = queue[p]
h = height[u]
discharge(u, capacities, flow, excess, seen, height, n)
if height[u] > h
queue.unshift(queue.delete_at(p))
p = 0
else
p += 1
end
end
flow[source].reduce(:+)
end
def push(u, v, capacities, flow, excess)
residual_capacity = capacities[u][v] - flow[u][v]
send = [excess[u], residual_capacity].min
flow[u][v] += send
flow[v][u] -= send
excess[u] -= send
excess[v] += send
end
def discharge(u, capacities, flow, excess, seen, height, n)
while excess[u] > 0
if seen[u] < n
v = seen[u]
if capacities[u][v] - flow[u][v] > 0 && height[u] > height[v]
push(u, v, capacities, flow, excess)
else
seen[u] += 1
end
else
relabel(u, capacities, flow, height, n)
seen[u] = 0
end
end
end
def relabel(u, capacities, flow, height, n)
min_height = Float::INFINITY
(0...n).each do |v|
if capacities[u][v] - flow[u][v] > 0
min_height = [min_height, height[v]].min
height[u] = min_height + 1
end
end
end
这是将数字对转换为数组的容量数组的代码
user_ids = Set.new
post_ids = Set.new
pairs.each do |p|
user_ids << p[:user_id]
post_ids << p[:post_id]
end
index_of_user_id = {}
index_of_post_id = {}
user_ids.each_with_index { |user_id, index| index_of_user_id[user_id] = 1 + index }
post_ids.each_with_index { |post_id, index| index_of_post_id[post_id] = 1 + index + user_ids.count }
source = 0
sink = user_ids.count + post_ids.count + 1
n = sink + 1
capacities = Array.new(n) { Array.new(n, 0) }
# source -> user_ids = 1
index_of_user_id.values.each { |i| capacities[source][i] = 1 }
# user_ids -> post_ids = 1
pairs.each { |p| capacities[index_of_user_id[p[:user_id]]][index_of_post_id[p[:post_id]]] = 1 }
# post_ids -> sink = 3
index_of_post_id.values.each { |i| capacities[i][sink] = 3 }