use std::collections::{HashMap, VecDeque};
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct TreeEdge {
pub source: usize,
pub target: usize,
pub capacity: f64,
}
impl TreeEdge {
pub fn new(source: usize, target: usize, capacity: f64) -> Self {
Self {
source,
target,
capacity,
}
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct GomoryHuTree {
pub(crate) vertex_count: usize,
pub(crate) edges: Vec<TreeEdge>,
}
impl GomoryHuTree {
pub fn new(edges: Vec<TreeEdge>, vertex_count: usize) -> Self {
Self {
edges,
vertex_count,
}
}
pub fn min_cut_value(&self, s: usize, t: usize) -> f64 {
if self.vertex_count == 0 {
return 0.0;
}
if s >= self.vertex_count || t >= self.vertex_count {
panic!(
"Vertex index out of bounds (s: {}, t: {}, vc: {})",
s, t, self.vertex_count
);
}
if s == t {
return f64::INFINITY;
}
let mut adj: HashMap<usize, Vec<(usize, f64)>> = HashMap::new();
for edge in &self.edges {
adj.entry(edge.source)
.or_default()
.push((edge.target, edge.capacity));
adj.entry(edge.target)
.or_default()
.push((edge.source, edge.capacity));
}
let mut queue: VecDeque<(usize, f64, Vec<usize>)> = VecDeque::new();
queue.push_back((s, f64::INFINITY, vec![s]));
let mut visited_bfs = vec![false; self.vertex_count];
visited_bfs[s] = true;
while let Some((curr, path_min_cap, current_path)) = queue.pop_front() {
if curr == t {
return path_min_cap; }
if let Some(neighbors) = adj.get(&curr) {
for &(neighbor, edge_cap) in neighbors {
if neighbor < self.vertex_count && !visited_bfs[neighbor] {
visited_bfs[neighbor] = true;
let mut next_path = current_path.clone(); next_path.push(neighbor);
queue.push_back((neighbor, path_min_cap.min(edge_cap), next_path));
}
}
}
}
0.0
}
pub fn to_dot(&self) -> String {
let mut dot = String::from("graph GomoryHuTree {\n");
if self.vertex_count == 0 {
} else if self.edges.is_empty() {
for i in 0..self.vertex_count {
dot.push_str(&format!(" {i}\n"));
}
} else {
for edge in &self.edges {
dot.push_str(&format!(
" {} -- {} [label=\"{:.2}\"]\n",
edge.source, edge.target, edge.capacity
));
}
}
dot.push_str("}\n");
dot
}
pub fn vertex_count(&self) -> usize {
self.vertex_count
}
pub fn edge_count(&self) -> usize {
self.edges.len()
}
}