#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Matrix {
rows: usize,
cols: usize,
vals: Vec<usize>,
}
impl Matrix {
pub fn square(n: usize) -> Self {
Matrix {
rows: n,
cols: n,
vals: vec![0; n * n],
}
}
pub fn rows(&self) -> usize {
self.rows
}
pub fn cols(&self) -> usize {
self.cols
}
fn _index(&self, index: (usize, usize)) -> usize {
let (row, col) = index;
row * self.rows + col
}
pub fn max_flow(&mut self) -> usize {
assert_eq!(self.rows(), self.cols());
let n = self.rows();
let mut flow = 0;
while let Some((new_flow, parents)) = bfs(self) {
flow += new_flow;
let mut curr_ix = n - 1;
while curr_ix > 0 {
let prev_ix = parents[curr_ix].unwrap();
self[(prev_ix, curr_ix)] -= new_flow;
self[(curr_ix, prev_ix)] += new_flow;
curr_ix = prev_ix;
}
}
flow
}
pub fn max_flow_mat(&self) -> (usize, Matrix) {
let mut output = self.clone();
let flow = output.max_flow();
let n = output.rows();
for r in 0..n {
for c in 0..n {
let index = (r, c);
let orig = self[index];
if orig > 0 {
output[index] = orig - output[index];
} else {
output[index] = 0;
}
}
}
(flow, output)
}
}
impl std::ops::Index<(usize, usize)> for Matrix {
type Output = usize;
fn index(&self, index: (usize, usize)) -> &Self::Output {
let ix = self._index(index);
&self.vals[ix]
}
}
impl std::ops::IndexMut<(usize, usize)> for Matrix {
fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output {
let ix = self._index(index);
&mut self.vals[ix]
}
}
impl std::fmt::Display for Matrix {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> Result<(), std::fmt::Error> {
for row in 0..self.rows {
if row > 0 {
writeln!(f)?;
}
write!(f, "{}", self[(row, 0)])?;
for col in 1..self.cols {
write!(f, ", {}", self[(row, col)])?;
}
}
Ok(())
}
}
fn bfs(capacity: &mut Matrix) -> Option<(usize, Vec<Option<usize>>)> {
use std::collections::VecDeque;
let n = capacity.rows();
let mut parents: Vec<Option<usize>> = vec![None; n];
let mut queue: VecDeque<(usize, usize)> = VecDeque::with_capacity(n);
queue.push_back((0, usize::MAX));
while let Some((node_ix, flow)) = queue.pop_front() {
for i in 0..n {
if capacity[(node_ix, i)] > 0 && parents[i].is_none() {
parents[i] = Some(node_ix);
let flow = std::cmp::min(flow, capacity[(node_ix, i)]);
if i == (n - 1) {
return Some((flow, parents));
}
queue.push_back((i, flow))
}
}
}
None
}
#[cfg(test)]
mod tests {
use super::Matrix;
#[test]
fn six_node_network_1() {
let expected_flow = 10;
let mut cap = Matrix::square(6);
cap[(0, 1)] = 7;
cap[(0, 4)] = 4;
cap[(1, 2)] = 5;
cap[(1, 3)] = 3;
cap[(2, 5)] = 8;
cap[(3, 2)] = 3;
cap[(3, 5)] = 5;
cap[(4, 1)] = 3;
cap[(4, 3)] = 2;
let (net_flow, flow_mat) = cap.max_flow_mat();
println!("{}", flow_mat);
assert_eq!(net_flow, expected_flow);
}
#[test]
fn six_node_network_2() {
let expected_flow = 6;
let mut cap = Matrix::square(6);
cap[(0, 1)] = 4;
cap[(0, 4)] = 2;
cap[(1, 2)] = 4;
cap[(1, 3)] = 2;
cap[(2, 5)] = 3;
cap[(3, 2)] = 1;
cap[(3, 5)] = 1;
cap[(4, 3)] = 1;
cap[(4, 5)] = 3;
let (net_flow, flow_mat) = cap.max_flow_mat();
println!("{}", flow_mat);
assert_eq!(net_flow, expected_flow);
}
#[test]
fn seven_node_network() {
let expected_flow = 5;
let mut cap = Matrix::square(7);
cap[(0, 1)] = 3;
cap[(0, 3)] = 3;
cap[(1, 2)] = 4;
cap[(2, 0)] = 3;
cap[(2, 3)] = 1;
cap[(2, 4)] = 2;
cap[(3, 4)] = 2;
cap[(3, 5)] = 6;
cap[(4, 1)] = 1;
cap[(4, 6)] = 1;
cap[(5, 6)] = 9;
let (net_flow, flow_mat) = cap.max_flow_mat();
println!("{}", flow_mat);
assert_eq!(net_flow, expected_flow);
}
}