use crate::traits::IndexDigraph;
use std::cmp::min;
use std::collections::VecDeque;
use crate::num::traits::NumAssign;
pub struct EdmondsKarp<'a, G, F>
where
G: IndexDigraph,
{
g: &'a G,
neighs: Vec<Vec<(usize, usize)>>,
pred: Vec<(usize, usize)>,
flow: Vec<F>,
queue: VecDeque<usize>,
value: F,
}
impl<'a, G, F> EdmondsKarp<'a, G, F>
where
G: IndexDigraph,
F: NumAssign + Ord + Copy,
{
pub fn new(g: &'a G) -> Self {
EdmondsKarp {
g,
neighs: g
.nodes()
.map(|u| {
g.outedges(u)
.map(|(e, v)| (g.edge_id(e) << 1, g.node_id(v)))
.chain(g.inedges(u).map(|(e, v)| ((g.edge_id(e) << 1) | 1, g.node_id(v))))
.collect()
})
.collect(),
pred: vec![(usize::max_value(), usize::max_value()); g.num_nodes()],
flow: vec![F::zero(); g.num_edges() * 2],
queue: VecDeque::with_capacity(g.num_nodes()),
value: F::zero(),
}
}
pub fn as_graph(&self) -> &'a G {
self.g
}
pub fn value(&self) -> F {
self.value
}
pub fn flow(&self, e: G::Edge<'_>) -> F {
self.flow[self.g.edge_id(e) << 1]
}
pub fn flow_iter<'b>(&'b self) -> impl Iterator<Item = (G::Edge<'a>, F)> + 'b {
self.g.edges().enumerate().map(move |(i, e)| (e, self.flow[i << 1]))
}
pub fn solve<Us>(&mut self, src: G::Node<'_>, snk: G::Node<'_>, upper: Us)
where
Us: Fn(G::Edge<'a>) -> F,
{
let src = self.g.node_id(src);
let snk = self.g.node_id(snk);
assert_ne!(src, snk, "Source and sink node must not be equal");
for (e, flw) in self.flow.iter_mut().enumerate() {
*flw = if (e & 1) == 0 {
F::zero()
} else {
upper(self.g.id2edge(e >> 1))
};
}
self.value = F::zero();
if self.g.num_edges() == 0 {
return;
}
loop {
self.pred.fill((usize::max_value(), usize::max_value()));
self.pred[src] = (0, 0);
self.queue.clear();
self.queue.push_back(src);
'bfs: while let Some(u) = self.queue.pop_front() {
for &(e, v) in &self.neighs[u] {
if self.pred[v].0 == usize::max_value() && !self.flow[e ^ 1].is_zero() {
self.pred[v] = (e, u);
self.queue.push_back(v);
if v == snk {
break 'bfs;
}
}
}
}
if self.pred[snk].0 == usize::max_value() {
break;
}
let mut v = snk;
let mut df = self.flow[self.pred[v].0 ^ 1];
while v != src {
let (e, u) = self.pred[v];
df = min(df, self.flow[e ^ 1]);
v = u;
}
debug_assert!(!df.is_zero());
let mut v = snk;
while v != src {
let (e, u) = self.pred[v];
self.flow[e] += df;
self.flow[e ^ 1] -= df;
v = u;
}
self.value += df;
}
}
pub fn mincut(&self) -> Vec<G::Node<'a>> {
self.g
.nodes()
.filter(|&u| self.pred[self.g.node_id(u)].0 != usize::max_value())
.collect()
}
}
pub fn edmondskarp<'a, G, F, Us>(
g: &'a G,
src: G::Node<'a>,
snk: G::Node<'a>,
upper: Us,
) -> (F, Vec<(G::Edge<'a>, F)>, Vec<G::Node<'a>>)
where
G: IndexDigraph,
F: 'a + NumAssign + Ord + Copy,
Us: Fn(G::Edge<'_>) -> F,
{
let mut maxflow = EdmondsKarp::new(g);
maxflow.solve(src, snk, upper);
(maxflow.value(), maxflow.flow_iter().collect(), maxflow.mincut())
}