diff --git a/graph/dinic.rs b/graph/dinic.rs new file mode 100644 index 0000000..ac16ef0 --- /dev/null +++ b/graph/dinic.rs @@ -0,0 +1,82 @@ +// loj-101.rs + +use std::collections::VecDeque; + +#[derive(Clone, Copy, Debug)] +struct Edge { + to: usize, + flow: i64, + cap: i64, + rev: usize, +} + +struct Net(Vec>, Vec, Vec); + +impl Net { + fn new(n: usize) -> Self { + Self(vec![vec![]; n+1], vec![0; n+1], vec![false; n+1]) + } + fn add_edge(&mut self, from: usize, to: usize, cap: i64) { + let to_edge = Edge {to, cap, flow: 0, rev: self.0[to].len()}; + self.0[from].push(to_edge); + let from_edge = Edge {to: from, flow: 0, cap: 0, rev: self.0[from].len() - 1}; + self.0[to].push(from_edge); + } + fn bfs(&mut self, s: usize, t: usize) -> bool { + self.1.fill(0); + let mut dq = VecDeque::new(); + self.1[s] = 1; + dq.push_back((s, 1)); + while let Some((v, l)) = dq.pop_front() { + for e in &self.0[v] { + if self.1[e.to] == 0 && e.cap > e.flow { + self.1[e.to] = l + 1; + dq.push_back((e.to, l + 1)); + } + } + } + self.1[t] != 0 + } + fn dfs(&mut self, s: usize, t: usize, cap: i64) -> i64 { + if self.2[s] { return 0; } + self.2[s] = true; + if s == t { return cap; } + let mut res = 0; + let n = self.0[s].len(); + for i in 0..n { + let e = self.0[s][i]; + if e.cap > e.flow && self.1[e.to] == self.1[s] + 1 { + let new = self.dfs(e.to, t, (cap - res).min(e.cap - e.flow)); + self.0[s][i].flow += new; + self.0[e.to][e.rev].flow -= new; + res += new; + if res == cap { return res; } + } + } + res + } + fn max_flow(&mut self, s: usize, t: usize) -> i64 { + let mut res = 0; + while self.bfs(s, t) { + self.2.fill(false); + res += self.dfs(s, t, i64::MAX); + } + res + } +} + +fn main() { + let mut buf = String::new(); + std::io::stdin().read_line(&mut buf).ok(); + let nmst: Vec = buf.trim().split(' ').map(|x|x.parse::().unwrap()).collect::>(); + let (n, m, s, t) = (nmst[0], nmst[1], nmst[2], nmst[3]); + let mut net = Net::new(n); + for _ in 0..m { + buf.clear(); + std::io::stdin().read_line(&mut buf).ok(); + let uvc: Vec = buf.trim().split(' ').map(|x|x.parse::().unwrap()).collect::>(); + let (u, v, c) = (uvc[0] as usize, uvc[1] as usize, uvc[2]); + net.add_edge(u, v, c); + } + println!("{}", net.max_flow(s, t)); +}