use crate::maxflow::MaxFlow;
use crate::adapters::{Network, NetworkEdge};
use crate::traits::{Directed, GraphSize, IndexDigraph, IndexGraph};
use crate::vec::{EdgeVec, NodeVec};
use std::cmp::min;
use std::collections::VecDeque;
use crate::num::traits::NumAssign;
pub struct EdmondsKarp<'a, G, F>
where
G: 'a + IndexDigraph<'a>,
{
g: Network<'a, G>,
pred: NodeVec<'a, Network<'a, G>, Option<NetworkEdge<G::Edge>>>,
flow: EdgeVec<'a, Network<'a, G>, F>,
queue: VecDeque<G::Node>,
value: F,
}
impl<'a, G, F> MaxFlow<'a> for EdmondsKarp<'a, G, F>
where
'a: 'a,
G: IndexDigraph<'a>,
F: NumAssign + Ord + Copy,
{
type Graph = G;
type Flow = F;
fn new(g: &'a G) -> Self {
EdmondsKarp {
g: Network::new(g),
pred: NodeVec::new(Network::new(g), None),
flow: EdgeVec::new(Network::new(g), F::zero()),
queue: VecDeque::with_capacity(g.num_nodes()),
value: F::zero(),
}
}
fn as_graph(&self) -> &'a Self::Graph {
self.g.as_graph()
}
fn value(&self) -> F {
self.value
}
fn flow(&self, e: G::Edge) -> F {
self.flow[self.g.from_edge(e)]
}
fn solve<Us>(&mut self, src: G::Node, snk: G::Node, upper: Us)
where
Us: Fn(G::Edge) -> Self::Flow,
{
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] = if e.is_forward() { F::zero() } else { upper(e.edge()) };
}
self.value = F::zero();
if self.g.num_edges() == 0 {
return;
}
loop {
for u in self.g.nodes() {
self.pred[u] = None
}
self.pred[src] = Some(self.g.id2edge(0));
self.queue.clear();
self.queue.push_back(src);
'bfs: while let Some(u) = self.queue.pop_front() {
for (e, v) in self.g.outedges(u) {
if self.pred[v].is_none() && !self.flow[e.reverse()].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 v = snk;
let e = self.pred[v].unwrap();
let mut df = self.flow[e.reverse()];
v = self.g.src(e);
while v != src {
let e = self.pred[v].unwrap();
df = min(df, self.flow[e.reverse()]);
v = self.g.src(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[e.reverse()] -= df;
v = self.g.src(e);
}
self.value += df;
}
}
fn mincut(&self) -> Vec<G::Node> {
self.g.nodes().filter(|&u| self.pred[u].is_some()).collect()
}
}