competitive_programming_rs/graph/
min_cost_flow.rs1pub mod primal_dual {
2 use std::cmp;
3 use std::collections::BinaryHeap;
4 type Flow = i64;
5 type Cost = i64;
6 const INF: Cost = 1 << 60;
7 struct Edge {
8 to: usize,
9 capacity: Flow,
10 flow: Flow,
11 cost: Cost,
12 reverse_to: usize,
13 }
14 impl Edge {
15 fn residue(&self) -> Flow {
16 self.capacity - self.flow
17 }
18 }
19
20 pub struct MinimumCostFlowSolver {
21 graph: Vec<Vec<Edge>>,
22 previous_edge: Vec<(usize, usize)>,
23 }
24
25 impl MinimumCostFlowSolver {
26 pub fn new(n: usize) -> Self {
27 MinimumCostFlowSolver {
28 graph: (0..n).map(|_| Vec::new()).collect(),
29 previous_edge: vec![(0, 0); n],
30 }
31 }
32
33 pub fn add_edge(&mut self, from: usize, to: usize, capacity: Flow, cost: Cost) {
34 let reverse_from = self.graph[to].len();
35 let reverse_to = self.graph[from].len();
36 self.graph[from].push(Edge {
37 to,
38 capacity,
39 flow: 0,
40 cost,
41 reverse_to: reverse_from,
42 });
43 self.graph[to].push(Edge {
44 to: from,
45 capacity,
46 flow: capacity,
47 cost: -cost,
48 reverse_to,
49 });
50 }
51
52 pub fn solve(&mut self, source: usize, sink: usize, mut flow: Flow) -> Option<Flow> {
54 let n = self.graph.len();
55 let mut result = 0;
56 let mut h = vec![0; n];
57 let mut q: BinaryHeap<(Cost, usize)> = BinaryHeap::new();
58 while flow > 0 {
59 let mut dist = vec![INF; n];
60 dist[source] = 0;
61 q.push((0, source));
62 while let Some((current_dist, v)) = q.pop() {
63 if dist[v] < current_dist {
64 continue;
65 }
66 for (i, e) in self.graph[v].iter().enumerate() {
67 if e.residue() == 0 {
68 continue;
69 }
70 if dist[e.to] + h[e.to] > current_dist + h[v] + e.cost {
71 dist[e.to] = current_dist + h[v] + e.cost - h[e.to];
72 self.previous_edge[e.to] = (v, i);
73 q.push((dist[e.to], e.to));
74 }
75 }
76 }
77
78 if dist[sink] == INF {
79 return None;
80 }
81
82 for i in 0..n {
83 h[i] += dist[i];
84 }
85 let mut df = flow;
86 let mut v = sink;
87 while v != source {
88 let (prev_v, prev_e) = self.previous_edge[v];
89 df = cmp::min(df, self.graph[prev_v][prev_e].residue());
90 v = prev_v;
91 }
92 flow -= df;
93 result += df * h[sink];
94 let mut v = sink;
95 while v != source {
96 let (prev_v, prev_e) = self.previous_edge[v];
97 self.graph[prev_v][prev_e].flow += df;
98 let reversed_edge_id = self.graph[prev_v][prev_e].reverse_to;
99 self.graph[v][reversed_edge_id].flow -= df;
100 v = prev_v;
101 }
102 }
103 Some(result)
104 }
105
106 pub fn neg_solve(&mut self, source: usize, sink: usize, mut flow: Flow) -> Option<Flow> {
109 let n = self.graph.len();
110 let mut result = 0;
111 while flow > 0 {
112 let mut dist = vec![INF; n];
113 dist[source] = 0;
114 loop {
115 let mut updated = false;
116 for v in 0..n {
117 if dist[v] == INF {
118 continue;
119 }
120
121 for (i, e) in self.graph[v].iter().enumerate() {
122 if e.residue() == 0 {
123 continue;
124 }
125 if dist[e.to] > dist[v] + e.cost {
126 dist[e.to] = dist[v] + e.cost;
127 self.previous_edge[e.to] = (v, i);
128 updated = true;
129 }
130 }
131 }
132 if !updated {
133 break;
134 }
135 }
136
137 if dist[sink] == INF {
138 return None;
139 }
140
141 let mut df = flow;
142 let mut v = sink;
143 while v != source {
144 let (prev_v, prev_e) = self.previous_edge[v];
145 df = cmp::min(df, self.graph[prev_v][prev_e].residue());
146 v = prev_v;
147 }
148 flow -= df;
149 result += df * dist[sink];
150 let mut v = sink;
151 while v != source {
152 let (prev_v, prev_e) = self.previous_edge[v];
153 self.graph[prev_v][prev_e].flow += df;
154 let reversed_edge_id = self.graph[prev_v][prev_e].reverse_to;
155 self.graph[v][reversed_edge_id].flow -= df;
156 v = prev_v;
157 }
158 }
159 Some(result)
160 }
161 }
162}
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167 use crate::utils::test_helper::Tester;
168
169 #[test]
170 fn solve_grl_6_b() {
171 let tester = Tester::new("./assets/GRL_6_B/in/", "./assets/GRL_6_B/out/");
172 tester.test_solution(|sc| {
173 let v: usize = sc.read();
174 let e: usize = sc.read();
175 let f: i64 = sc.read();
176
177 let mut solver = primal_dual::MinimumCostFlowSolver::new(v);
178 for _ in 0..e {
179 let u: usize = sc.read();
180 let v: usize = sc.read();
181 let c: i64 = sc.read();
182 let d: i64 = sc.read();
183 solver.add_edge(u, v, c, d);
184 }
185
186 let ans = match solver.solve(0, v - 1, f) {
187 Some(flow) => flow,
188 None => -1,
189 };
190 sc.write(format!("{}\n", ans));
191 });
192 }
193
194 #[test]
195 fn solve_grl_6_b_negative() {
196 let tester = Tester::new("./assets/GRL_6_B/in/", "./assets/GRL_6_B/out/");
197 tester.test_solution(|sc| {
198 let v: usize = sc.read();
199 let e: usize = sc.read();
200 let f: i64 = sc.read();
201
202 let mut solver = primal_dual::MinimumCostFlowSolver::new(v);
203 for _ in 0..e {
204 let u: usize = sc.read();
205 let v: usize = sc.read();
206 let c: i64 = sc.read();
207 let d: i64 = sc.read();
208 solver.add_edge(u, v, c, d);
209 }
210
211 let ans = match solver.neg_solve(0, v - 1, f) {
212 Some(flow) => flow,
213 None => -1,
214 };
215 sc.write(format!("{}\n", ans));
216 });
217 }
218}