use maxflow::MaxFlow;
use graph::{IndexBiEdgeVec, IndexNetwork, IndexNodeVec};
use EdgeMap;
use std::cmp::min;
use std::collections::VecDeque;
use num::traits::NumAssign;
pub struct EdmondsKarp<'a, G, F>
where
G: 'a + IndexNetwork<'a>,
{
g: &'a G,
pred: IndexNodeVec<'a, G, Option<G::Edge>>,
flow: IndexBiEdgeVec<'a, G, F>,
queue: VecDeque<G::Node>,
value: F,
}
impl<'a, G, F> MaxFlow<'a> for EdmondsKarp<'a, G, F>
where
G: IndexNetwork<'a>,
F: NumAssign + Ord + Copy,
{
type Graph = G;
type Flow = F;
fn new(g: &'a G) -> Self {
EdmondsKarp {
g: g,
pred: idxnodevec![g; None],
flow: idxbiedgevec![g; F::zero()],
queue: VecDeque::with_capacity(g.num_nodes()),
value: F::zero(),
}
}
fn as_graph(&self) -> &'a Self::Graph {
self.g
}
fn value(&self) -> F {
self.value
}
fn flow(&self, e: G::Edge) -> F {
self.flow[self.g.forward(e)]
}
fn solve<Us>(&mut self, src: G::Node, snk: G::Node, upper: Us)
where
Us: EdgeMap<'a, G, F>,
{
assert_ne!(
self.g.node_id(src),
self.g.node_id(snk),
"Source and sink node must not be equal"
);
for e in self.g.edges() {
self.flow[e] = F::zero();
self.flow[self.g.reverse(e)] = upper[e];
}
if self.g.num_edges() == 0 {
return;
}
let src_e = self.g.id2edge(0);
let bound = self.g.edges().map(|e| upper[e]).max().unwrap();
self.value = F::zero();
loop {
for u in self.g.nodes() {
self.pred[u] = None
}
self.pred[src] = Some(src_e);
self.queue.clear();
self.queue.push_back(src);
'bfs: while let Some(u) = self.queue.pop_front() {
for (e, v) in self.g.neighs(u) {
if self.pred[v].is_none() && !self.flow[self.g.reverse(e)].is_zero() {
self.pred[v] = Some(e);
self.queue.push_back(v);
if v == snk {
break 'bfs;
}
}
}
}
if self.pred[snk].is_none() {
break;
}
let mut df = bound;
let mut v = snk;
while v != src {
let e = self.pred[v].unwrap();
df = min(df, self.flow[self.g.reverse(e)]);
v = self.g.bisrc(e);
}
debug_assert!(!df.is_zero());
let mut v = snk;
while v != src {
let e = self.pred[v].unwrap();
self.flow[e] += df;
self.flow[self.g.reverse(e)] -= df;
v = self.g.bisrc(e);
}
self.value += df;
}
}
fn mincut(&self) -> Vec<G::Node> {
self.g.nodes().filter(|&u| self.pred[u].is_some()).collect()
}
}