use maxflow::MaxFlow;
use graph::{IndexBiEdgeVec, IndexNetwork, IndexNodeVec};
use EdgeMap;
use std::cmp::min;
use std::collections::VecDeque;
use num::traits::NumAssign;
pub struct Dinic<'a, G, F>
where
G: 'a + IndexNetwork<'a>,
{
g: &'a G,
nodes: IndexNodeVec<'a, G, NodeInfo<G::Edge>>,
edges: IndexBiEdgeVec<'a, G, EdgeInfo<G::Edge, F>>,
queue: VecDeque<G::Node>,
value: F,
}
#[derive(Clone)]
struct NodeInfo<E> {
dist: usize,
first_lvl: Option<E>,
}
#[derive(Clone)]
struct EdgeInfo<E, F> {
flow: F,
next_lvl: Option<E>,
}
impl<'a, G, F> MaxFlow<'a> for Dinic<'a, G, F>
where
G: IndexNetwork<'a>,
F: NumAssign + Ord + Copy,
{
type Graph = G;
type Flow = F;
fn new(g: &'a G) -> Self {
Dinic {
g: g,
nodes: idxnodevec![g; NodeInfo { dist: 0, first_lvl: None }],
edges: idxbiedgevec![g; EdgeInfo { flow: F::zero(), next_lvl: None }],
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.edges[self.g.forward(e)].flow
}
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.edges[e].flow = F::zero();
self.edges[self.g.reverse(e)].flow = upper[e];
}
let mut bound = F::zero();
for (e, _) in self.g.outedges(src) {
bound += upper[e];
}
self.value = F::zero();
while self.search(src, snk) {
self.value += self.augment(src, snk, bound);
}
}
fn mincut(&self) -> Vec<G::Node> {
let n = self.g.num_nodes();
self.g.nodes().filter(|&u| self.nodes[u].dist < n).collect()
}
}
impl<'a, G, F> Dinic<'a, G, F>
where
G: IndexNetwork<'a>,
F: NumAssign + Ord + Copy,
{
fn search(&mut self, src: G::Node, snk: G::Node) -> bool {
let n = self.g.num_nodes();
for u in self.g.nodes() {
self.nodes[u].dist = n;
self.nodes[u].first_lvl = None;
}
self.nodes[src].dist = 0;
self.queue.clear();
self.queue.push_back(src);
let mut snk_d = n;
while let Some(u) = self.queue.pop_front() {
let d = self.nodes[u].dist;
if d >= snk_d {
return true;
}
for (e, v) in self.g.neighs(u) {
let f = self.g.reverse(e);
if self.edges[f].flow > F::zero() {
if self.nodes[v].dist == n {
self.nodes[v].dist = d + 1;
self.queue.push_back(v);
if v == snk {
snk_d = d + 1
}
} else if self.nodes[v].dist != d + 1 {
continue;
}
self.edges[e].next_lvl = self.nodes[u].first_lvl;
self.nodes[u].first_lvl = Some(e);
}
}
}
false
}
fn augment(&mut self, src: G::Node, snk: G::Node, target_flow: F) -> F {
if src == snk {
return target_flow;
}
let mut df = F::zero();
while let Some(e) = self.nodes[src].first_lvl {
let f = self.g.reverse(e);
let rem_cap = min(self.edges[f].flow, target_flow - df);
if rem_cap > F::zero() {
debug_assert!(self.g.bisrc(e) == src);
debug_assert!(self.g.bisnk(e) != src);
let cf = self.augment(self.g.bisnk(e), snk, rem_cap);
self.edges[e].flow += cf;
self.edges[f].flow -= cf;
df += cf;
if df == target_flow {
break;
}
}
self.nodes[src].first_lvl = self.edges[e].next_lvl;
}
if df.is_zero() {
self.nodes[src].first_lvl = None;
}
df
}
}