|
| 1 | +use crate::internal_type_traits::Integral; |
1 | 2 |
|
| 3 | +pub struct MinCostFlowEdge<T> { |
| 4 | + pub from: usize, |
| 5 | + pub to: usize, |
| 6 | + pub cap: T, |
| 7 | + pub flow: T, |
| 8 | + pub cost: T, |
| 9 | +} |
| 10 | + |
| 11 | +pub struct MinCostFlowGraph<T> { |
| 12 | + pos: Vec<(usize, usize)>, |
| 13 | + g: Vec<Vec<_Edge<T>>>, |
| 14 | + cost_sum: T, |
| 15 | +} |
| 16 | + |
| 17 | +impl<T> MinCostFlowGraph<T> |
| 18 | +where |
| 19 | + T: Integral + std::ops::Neg<Output = T>, |
| 20 | +{ |
| 21 | + pub fn new(n: usize) -> Self { |
| 22 | + Self { |
| 23 | + pos: vec![], |
| 24 | + g: (0..n).map(|_| vec![]).collect(), |
| 25 | + cost_sum: T::zero(), |
| 26 | + } |
| 27 | + } |
| 28 | + |
| 29 | + pub fn get_edge(&self, i: usize) -> MinCostFlowEdge<T> { |
| 30 | + assert!(i < self.pos.len()); |
| 31 | + let e = &self.g[self.pos[i].0][self.pos[i].1]; |
| 32 | + let re = &self.g[e.to][e.rev]; |
| 33 | + MinCostFlowEdge { |
| 34 | + from: self.pos[i].0, |
| 35 | + to: e.to, |
| 36 | + cap: e.cap + re.cap, |
| 37 | + flow: re.cap, |
| 38 | + cost: e.cost, |
| 39 | + } |
| 40 | + } |
| 41 | + |
| 42 | + pub fn edges(&self) -> Vec<MinCostFlowEdge<T>> { |
| 43 | + let m = self.pos.len(); |
| 44 | + let mut result = vec![]; |
| 45 | + for i in 0..m { |
| 46 | + result.push(self.get_edge(i)); |
| 47 | + } |
| 48 | + result |
| 49 | + } |
| 50 | + |
| 51 | + pub fn add_edge(&mut self, from: usize, to: usize, cap: T, cost: T) -> usize { |
| 52 | + assert!(from < self.g.len()); |
| 53 | + assert!(to < self.g.len()); |
| 54 | + assert_ne!(from, to); |
| 55 | + assert!(cap >= T::zero()); |
| 56 | + assert!(cost >= T::zero()); |
| 57 | + |
| 58 | + self.pos.push((from, self.g[from].len())); |
| 59 | + self.cost_sum += cost; |
| 60 | + |
| 61 | + let rev = self.g[to].len(); |
| 62 | + self.g[from].push(_Edge { to, rev, cap, cost }); |
| 63 | + |
| 64 | + let rev = self.g[from].len() - 1; |
| 65 | + self.g[to].push(_Edge { |
| 66 | + to: from, |
| 67 | + rev, |
| 68 | + cap: T::zero(), |
| 69 | + cost: -cost, |
| 70 | + }); |
| 71 | + |
| 72 | + self.pos.len() - 1 |
| 73 | + } |
| 74 | + |
| 75 | + /// Returns (maximum flow, cost) |
| 76 | + pub fn flow(&mut self, source: usize, sink: usize, flow_limit: T) -> (T, T) { |
| 77 | + self.slope(source, sink, flow_limit).pop().unwrap() |
| 78 | + } |
| 79 | + |
| 80 | + pub fn slope(&mut self, source: usize, sink: usize, flow_limit: T) -> Vec<(T, T)> { |
| 81 | + let n = self.g.len(); |
| 82 | + assert!(source < n); |
| 83 | + assert!(sink < n); |
| 84 | + assert_ne!(source, sink); |
| 85 | + |
| 86 | + let mut dual = vec![T::zero(); n]; |
| 87 | + let mut prev_v = vec![0; n]; |
| 88 | + let mut prev_e = vec![0; n]; |
| 89 | + let mut flow = T::zero(); |
| 90 | + let mut cost = T::zero(); |
| 91 | + let mut prev_cost: Option<T> = None; |
| 92 | + let mut result = vec![(flow, cost)]; |
| 93 | + while flow < flow_limit { |
| 94 | + if !self.refine_dual(source, sink, &mut dual, &mut prev_v, &mut prev_e) { |
| 95 | + break; |
| 96 | + } |
| 97 | + |
| 98 | + let mut c = flow_limit - flow; |
| 99 | + let mut v = sink; |
| 100 | + while v != source { |
| 101 | + c = std::cmp::min(c, self.g[prev_v[v]][prev_e[v]].cap); |
| 102 | + v = prev_v[v]; |
| 103 | + } |
| 104 | + |
| 105 | + let mut v = sink; |
| 106 | + while v != source { |
| 107 | + self.g[prev_v[v]][prev_e[v]].cap -= c; |
| 108 | + let rev = self.g[prev_v[v]][prev_e[v]].rev; |
| 109 | + self.g[v][rev].cap += c; |
| 110 | + v = prev_v[v]; |
| 111 | + } |
| 112 | + |
| 113 | + let d = -dual[source]; |
| 114 | + flow += c; |
| 115 | + cost += d * c; |
| 116 | + if prev_cost == Some(d) { |
| 117 | + assert!(result.pop().is_some()); |
| 118 | + } |
| 119 | + result.push((flow, cost)); |
| 120 | + prev_cost = Some(cost); |
| 121 | + } |
| 122 | + result |
| 123 | + } |
| 124 | + |
| 125 | + fn refine_dual( |
| 126 | + &self, |
| 127 | + source: usize, |
| 128 | + sink: usize, |
| 129 | + dual: &mut [T], |
| 130 | + pv: &mut [usize], |
| 131 | + pe: &mut [usize], |
| 132 | + ) -> bool { |
| 133 | + let n = self.g.len(); |
| 134 | + let mut dist = vec![self.cost_sum; n]; |
| 135 | + let mut vis = vec![false; n]; |
| 136 | + |
| 137 | + let mut que = std::collections::BinaryHeap::new(); |
| 138 | + dist[source] = T::zero(); |
| 139 | + que.push((std::cmp::Reverse(T::zero()), source)); |
| 140 | + while let Some((_, v)) = que.pop() { |
| 141 | + if vis[v] { |
| 142 | + continue; |
| 143 | + } |
| 144 | + vis[v] = true; |
| 145 | + if v == sink { |
| 146 | + break; |
| 147 | + } |
| 148 | + |
| 149 | + for (i, e) in self.g[v].iter().enumerate() { |
| 150 | + if vis[e.to] || e.cap == T::zero() { |
| 151 | + continue; |
| 152 | + } |
| 153 | + |
| 154 | + let cost = e.cost - dual[e.to] + dual[v]; |
| 155 | + if dist[e.to] - dist[v] > cost { |
| 156 | + dist[e.to] = dist[v] + cost; |
| 157 | + pv[e.to] = v; |
| 158 | + pe[e.to] = i; |
| 159 | + que.push((std::cmp::Reverse(dist[e.to]), e.to)); |
| 160 | + } |
| 161 | + } |
| 162 | + } |
| 163 | + |
| 164 | + if !vis[sink] { |
| 165 | + return false; |
| 166 | + } |
| 167 | + |
| 168 | + for v in 0..n { |
| 169 | + if !vis[v] { |
| 170 | + continue; |
| 171 | + } |
| 172 | + dual[v] -= dist[sink] - dist[v]; |
| 173 | + } |
| 174 | + true |
| 175 | + } |
| 176 | +} |
| 177 | + |
| 178 | +struct _Edge<T> { |
| 179 | + to: usize, |
| 180 | + rev: usize, |
| 181 | + cap: T, |
| 182 | + cost: T, |
| 183 | +} |
| 184 | + |
| 185 | +#[cfg(test)] |
| 186 | +mod tests { |
| 187 | + use super::*; |
| 188 | + |
| 189 | + #[test] |
| 190 | + fn test_min_cost_flow() { |
| 191 | + let mut graph = MinCostFlowGraph::new(4); |
| 192 | + graph.add_edge(0, 1, 2, 1); |
| 193 | + graph.add_edge(0, 2, 1, 2); |
| 194 | + graph.add_edge(1, 2, 1, 1); |
| 195 | + graph.add_edge(1, 3, 1, 3); |
| 196 | + graph.add_edge(2, 3, 2, 1); |
| 197 | + let (flow, cost) = graph.flow(0, 3, 2); |
| 198 | + assert_eq!(flow, 2); |
| 199 | + assert_eq!(cost, 6); |
| 200 | + } |
| 201 | +} |
0 commit comments