use crate::utils::num_traits::PrimInt;
use rustc_hash::FxHashMap;
#[derive(Debug, Clone)]
pub struct Edge<T> {
rev: usize,
from: usize,
to: usize,
cap: T,
original_cap: T,
}
impl<T: Clone> Edge<T> {
pub fn new(rev: usize, from: usize, to: usize, cap: T) -> Self {
Self {
rev,
from,
to,
cap: cap.clone(),
original_cap: cap,
}
}
}
type Graph<T> = Vec<Vec<Edge<T>>>;
#[derive(Debug)]
pub struct FordFulkerson<T> {
N: usize,
pub G: Graph<T>,
edge_id: FxHashMap<(usize, usize), usize>,
}
impl<T: PrimInt> FordFulkerson<T> {
pub fn new(n: usize) -> Self {
Self {
N: n,
G: vec![vec![]; n],
edge_id: FxHashMap::default(),
}
}
pub fn add_edge(&mut self, from: usize, to: usize, cap: T) {
let rev = self.G[to].len();
self.G[from].push(Edge::new(rev, from, to, cap));
let rrev = self.G[from].len() - 1;
self.G[to].push(Edge::new(rrev, to, from, T::zero()));
self.edge_id.insert((from, to), rrev);
}
fn dfs(u: usize, t: usize, f: T, G: &mut Graph<T>, visit: &mut [bool]) -> T {
if u == t {
return f;
}
visit[u] = true;
for i in 0..G[u].len() {
let v = G[u][i].to;
let cap = G[u][i].cap;
if visit[v] || cap <= T::zero() {
continue;
}
let d = Self::dfs(v, t, f.min(cap), G, visit);
if d > T::zero() {
G[u][i].cap = cap - d;
let r = G[u][i].rev;
G[v][r].cap = G[v][r].cap + d;
return d;
}
}
T::zero()
}
pub fn max_flow(&mut self, s: usize, t: usize) -> T {
let mut flow = T::zero();
let mut visit = vec![false; self.N];
loop {
visit.fill(false);
let f = Self::dfs(s, t, T::max_value(), &mut self.G, &mut visit);
if f.is_zero() {
break;
}
flow = flow + f;
}
flow
}
pub fn get_flow(&self, u: usize, v: usize) -> T {
let i = self.edge_id[&(u, v)];
let cap = self.G[u][i].cap;
let original = self.G[u][i].original_cap;
original - cap
}
}