use maxflow::MaxFlow;
use graph::IndexNetwork;
use vec::{NodeVec, BiEdgeVec, EdgeSlice};
use std::collections::VecDeque;
use std::cmp::min;
use num::traits::NumAssign;
pub struct EdmondsKarp<'a, G, F>
where G: 'a + IndexNetwork<'a>
{
g: &'a G,
pred: NodeVec<'a, G, Option<G::Edge>>,
flow: BiEdgeVec<'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: nodevec![g; None],
flow: biedgevec![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<'b>(&mut self,
src: G::Node, snk: G::Node,
upper: &EdgeSlice<'a, 'b, G, F>)
{
assert_ne!(self.g.node_id(src), self.g.node_id(snk), "Source and sink node must not be equal");
assert!(self.g.num_nodes() <= usize::max_value(),
"Too many nodes for internal integer type");
assert!(self.g.num_edges() <= usize::max_value(),
"Too many edges for internal integer type");
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 = *upper.iter().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()
}
}