algorithms_edu/algo/graph/network_flow/
edmonds_karp.rs1use super::{MaxFlowSolver, NetworkFlowAdjacencyList};
2use std::collections::VecDeque;
3
4pub struct EdmondsKarpSolver {}
5
6impl MaxFlowSolver for EdmondsKarpSolver {
7 fn max_flow(graph: &mut NetworkFlowAdjacencyList) -> i32 {
8 let n = graph.node_count();
9 let mut visited = vec![0; n];
10 let mut visited_token = 1;
11
12 let mut bfs = |visited_token| {
13 let mut q = VecDeque::with_capacity(n);
14 let mut prev = vec![None; n];
15 visited[graph.source] = visited_token;
16 q.push_back(graph.source);
17 while let Some(node) = q.pop_front() {
18 if node == graph.sink {
19 break;
20 }
21 for edge in &graph[node] {
22 let _edge = edge.borrow();
23 if _edge.reamaining_capacity() > 0 && visited[_edge.to] != visited_token {
24 visited[_edge.to] = visited_token;
25 prev[_edge.to] = Some(edge.clone());
26 q.push_back(_edge.to);
27 }
28 }
29 }
30 if prev[graph.sink].is_none() {
31 return 0;
32 }
33
34 let mut bottleneck = i32::MAX;
35 let mut node = graph.sink;
36
37 while let Some(prev_edge) = &prev[node] {
38 bottleneck = std::cmp::min(bottleneck, prev_edge.borrow().reamaining_capacity());
39 node = prev_edge.borrow().from;
40 }
41
42 node = graph.sink;
43
44 while let Some(prev_edge) = &prev[node] {
45 prev_edge.borrow_mut().augment(bottleneck);
46 node = prev_edge.borrow().from;
47 }
48
49 bottleneck
50 };
51 let mut flow = 0;
52 let mut f = -1;
53 while f != 0 {
54 f = bfs(visited_token);
55
56 flow += f;
57 visited_token += 1;
58 }
59 flow
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 fn test_max_flow(n: usize, edges: &[(usize, usize, i32)], expected_max_flow: i32) {
68 let mut graph = NetworkFlowAdjacencyList::from_edges(n, edges);
69 let max_flow = EdmondsKarpSolver::max_flow(&mut graph);
70 assert_eq!(max_flow, expected_max_flow);
71 }
72
73 #[test]
74 fn test_small_graph() {
75 test_max_flow(
76 6,
77 &[
78 (5, 0, 10),
80 (5, 1, 10),
81 (2, 4, 10),
83 (3, 4, 10),
84 (0, 1, 2),
86 (0, 2, 4),
87 (0, 3, 8),
88 (1, 3, 9),
89 (3, 2, 6),
90 ],
91 19,
92 );
93 }
94
95 #[test]
96 fn test_disconnected() {
97 test_max_flow(4, &[(3, 0, 9), (1, 2, 9)], 0);
98 }
99
100 #[test]
101 fn test_medium_graph() {
102 test_max_flow(
103 12,
104 &[
105 (11, 0, 5),
107 (11, 1, 20),
108 (11, 2, 10),
109 (7, 10, 7),
111 (8, 10, 15),
112 (9, 10, 60),
113 (0, 1, 3),
115 (0, 5, 4),
116 (1, 4, 14),
117 (1, 5, 14),
118 (2, 1, 5),
119 (2, 3, 4),
120 (3, 4, 3),
121 (3, 9, 11),
122 (4, 6, 4),
123 (4, 8, 22),
124 (5, 6, 8),
125 (5, 7, 3),
126 (6, 7, 12),
127 (7, 8, 9),
128 (8, 9, 11),
129 ],
130 29,
131 );
132 }
133}