use crate::graph::graph::Graph;
pub struct FordFullkerson {
    pub graph: Graph,
    pub used: Vec<bool>,
    pub flow: usize,
}
impl FordFullkerson {
    const INF: usize = 100_000_000_000_000_000;
    pub fn new(graph: Graph) -> Self {
        let used = vec![false; graph.n];
        let flow = Self::INF;
        Self { graph, used, flow }
    }
    pub fn dfs(&mut self, u: usize, t: usize, f: usize) -> usize {
        if u == t {
            return f;
        }
        self.used[u] = true;
        for i in 0..self.graph.graph[u].len() {
            let (v, cap) = self.graph.graph[u][i];
            let r = self.graph.rev[u][i];
            if !self.used[v] && cap > 0 {
                let d = self.dfs(v, t, f.min(cap));
                if d > 0 {
                    self.graph.graph[u][i].1 -= d;
                    self.graph.graph[v][r].1 += d;
                    return d;
                }
            }
        }
        0
    }
    pub fn solve(&mut self, s: usize, t: usize) -> usize {
        let mut flow = 0;
        loop {
            self.used = vec![false; self.graph.n];
            let f: usize = self.dfs(s, t, FordFullkerson::INF);
            if f == 0 {
                return flow;
            }
            flow += f;
        }
    }
}
#[cfg(test)]
mod test_lowlink {
    use crate::graph::ford_fullkerson::FordFullkerson;
    use crate::graph::graph::Graph;
    #[test]
    fn it_works() {
        let mut graph = Graph::new(4, true);
        graph.connect_with_residual(0, 1, 2);
        graph.connect_with_residual(0, 2, 1);
        graph.connect_with_residual(1, 2, 1);
        graph.connect_with_residual(1, 3, 1);
        graph.connect_with_residual(2, 3, 2);
        let mut solver = FordFullkerson::new(graph);
        let maxflow = solver.solve(0, 3);
        assert_eq!(maxflow, 3);
    }
}