ruvector_dag/mincut/
local_kcut.rs1use super::engine::{FlowEdge, MinCutResult};
4use std::collections::{HashMap, HashSet, VecDeque};
5
6pub struct LocalKCut {
8 visited: HashSet<usize>,
9 distance: HashMap<usize, usize>,
10}
11
12impl LocalKCut {
13 pub fn new() -> Self {
14 Self {
15 visited: HashSet::new(),
16 distance: HashMap::new(),
17 }
18 }
19
20 pub fn compute(
23 &mut self,
24 graph: &HashMap<usize, Vec<FlowEdge>>,
25 source: usize,
26 sink: usize,
27 depth: usize,
28 ) -> MinCutResult {
29 self.visited.clear();
30 self.distance.clear();
31
32 let source_reachable = self.limited_bfs(graph, source, depth);
34
35 let sink_reachable = self.limited_bfs(graph, sink, depth);
37
38 let mut cut_edges = Vec::new();
40 let mut cut_value = 0.0;
41
42 for &node in &source_reachable {
43 if let Some(edges) = graph.get(&node) {
44 for edge in edges {
45 if !source_reachable.contains(&edge.to) && edge.capacity > 0.0 {
46 cut_edges.push((edge.from, edge.to));
47 cut_value += edge.capacity;
48 }
49 }
50 }
51 }
52
53 MinCutResult {
54 cut_value,
55 source_side: source_reachable,
56 sink_side: sink_reachable,
57 cut_edges,
58 }
59 }
60
61 fn limited_bfs(
62 &mut self,
63 graph: &HashMap<usize, Vec<FlowEdge>>,
64 start: usize,
65 max_depth: usize,
66 ) -> HashSet<usize> {
67 let mut reachable = HashSet::new();
68 let mut queue = VecDeque::new();
69
70 queue.push_back((start, 0));
71 reachable.insert(start);
72
73 while let Some((node, depth)) = queue.pop_front() {
74 if depth >= max_depth {
75 continue;
76 }
77
78 if let Some(edges) = graph.get(&node) {
79 for edge in edges {
80 if edge.capacity > edge.flow && !reachable.contains(&edge.to) {
81 reachable.insert(edge.to);
82 queue.push_back((edge.to, depth + 1));
83 }
84 }
85 }
86 }
87
88 reachable
89 }
90}