Skip to content

Commit 6a8e6dc

Browse files
committed
Implement mincostflow
1 parent 6e34caa commit 6a8e6dc

File tree

2 files changed

+235
-0
lines changed

2 files changed

+235
-0
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ pub(crate) mod internal_scc;
1818
pub(crate) mod internal_type_traits;
1919

2020
pub use fenwicktree::FenwickTree;
21+
pub use mincostflow::MinCostFlowGraph;

src/mincostflow.rs

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,235 @@
1+
pub struct MinCostFlowEdge<T> {
2+
pub from: usize,
3+
pub to: usize,
4+
pub cap: T,
5+
pub flow: T,
6+
pub cost: T,
7+
}
18

9+
pub struct MinCostFlowGraph<T> {
10+
pos: Vec<(usize, usize)>,
11+
g: Vec<Vec<_Edge<T>>>,
12+
cost_sum: T,
13+
}
14+
15+
impl<T> MinCostFlowGraph<T>
16+
where
17+
T: Number + std::ops::Neg<Output = T>,
18+
{
19+
pub fn new(n: usize) -> Self {
20+
Self {
21+
pos: vec![],
22+
g: (0..n).map(|_| vec![]).collect(),
23+
cost_sum: T::zero(),
24+
}
25+
}
26+
27+
pub fn get_edge(&self, i: usize) -> MinCostFlowEdge<T> {
28+
assert!(i < self.pos.len());
29+
let e = &self.g[self.pos[i].0][self.pos[i].1];
30+
let re = &self.g[e.to][e.rev];
31+
MinCostFlowEdge {
32+
from: self.pos[i].0,
33+
to: e.to,
34+
cap: e.cap + re.cap,
35+
flow: re.cap,
36+
cost: e.cost,
37+
}
38+
}
39+
40+
pub fn edges(&self) -> Vec<MinCostFlowEdge<T>> {
41+
let m = self.pos.len();
42+
let mut result = vec![];
43+
for i in 0..m {
44+
result.push(self.get_edge(i));
45+
}
46+
result
47+
}
48+
49+
pub fn add_edge(&mut self, from: usize, to: usize, cap: T, cost: T) -> usize {
50+
assert!(from < self.g.len());
51+
assert!(to < self.g.len());
52+
assert_ne!(from, to);
53+
self.pos.push((from, self.g[from].len()));
54+
self.cost_sum += cost;
55+
56+
let rev = self.g[to].len();
57+
self.g[from].push(_Edge { to, rev, cap, cost });
58+
59+
let rev = self.g[from].len() - 1;
60+
self.g[to].push(_Edge {
61+
to: from,
62+
rev,
63+
cap: T::zero(),
64+
cost: -cost,
65+
});
66+
67+
self.pos.len() - 1
68+
}
69+
70+
/// Returns (maximum flow, cost)
71+
pub fn flow(&mut self, s: usize, t: usize, flow_limit: T) -> (T, T) {
72+
self.slope(s, t, flow_limit).last().unwrap().clone()
73+
}
74+
75+
pub fn slope(&mut self, s: usize, t: usize, flow_limit: T) -> Vec<(T, T)> {
76+
let n = self.g.len();
77+
assert!(s < n);
78+
assert!(t < n);
79+
assert_ne!(s, t);
80+
81+
let mut dual = vec![T::zero(); n];
82+
let mut prev_v = vec![0; n];
83+
let mut prev_e = vec![0; n];
84+
let mut flow = T::zero();
85+
let mut cost = T::zero();
86+
let mut prev_cost: Option<T> = None;
87+
let mut result = vec![(flow, cost)];
88+
while flow < flow_limit {
89+
if !self.dual_ref(s, t, &mut dual, &mut prev_v, &mut prev_e) {
90+
break;
91+
}
92+
let mut c = flow_limit - flow;
93+
94+
let mut v = t;
95+
while v != s {
96+
c = std::cmp::min(c, self.g[prev_v[v]][prev_e[v]].cap);
97+
v = prev_v[v];
98+
}
99+
100+
let mut v = t;
101+
while v != s {
102+
self.g[prev_v[v]][prev_e[v]].cap -= c;
103+
let rev = self.g[prev_v[v]][prev_e[v]].rev;
104+
self.g[v][rev].cap += c;
105+
v = prev_v[v];
106+
}
107+
108+
let d = -dual[s];
109+
flow += c;
110+
cost += d * c;
111+
if prev_cost == Some(d) {
112+
assert!(result.pop().is_some());
113+
}
114+
result.push((flow, cost));
115+
prev_cost = Some(cost);
116+
}
117+
result
118+
}
119+
120+
fn dual_ref(
121+
&self,
122+
s: usize,
123+
t: usize,
124+
dual: &mut [T],
125+
pv: &mut [usize],
126+
pe: &mut [usize],
127+
) -> bool {
128+
let n = self.g.len();
129+
let mut dist = vec![self.cost_sum; n];
130+
let mut vis = vec![false; n];
131+
132+
let mut que = std::collections::BinaryHeap::new();
133+
dist[s] = T::zero();
134+
que.push((std::cmp::Reverse(T::zero()), s));
135+
while let Some((_, v)) = que.pop() {
136+
if vis[v] {
137+
continue;
138+
}
139+
vis[v] = true;
140+
if v == t {
141+
break;
142+
}
143+
144+
for (i, e) in self.g[v].iter().enumerate() {
145+
if vis[e.to] || e.cap == T::zero() {
146+
continue;
147+
}
148+
149+
let cost = e.cost - dual[e.to] + dual[v];
150+
if dist[e.to] - dist[v] > cost {
151+
dist[e.to] = dist[v] + cost;
152+
pv[e.to] = v;
153+
pe[e.to] = i;
154+
que.push((std::cmp::Reverse(dist[e.to]), e.to));
155+
}
156+
}
157+
}
158+
159+
if !vis[t] {
160+
return false;
161+
}
162+
163+
for v in 0..n {
164+
if !vis[v] {
165+
continue;
166+
}
167+
dual[v] = dual[v] - (dist[t] - dist[v]);
168+
}
169+
true
170+
}
171+
}
172+
173+
struct _Edge<T> {
174+
to: usize,
175+
rev: usize,
176+
cap: T,
177+
cost: T,
178+
}
179+
180+
// TODO migrate to common type
181+
pub trait Number:
182+
Copy
183+
+ Ord
184+
+ std::ops::Not<Output = Self>
185+
+ std::ops::Add<Output = Self>
186+
+ std::ops::Sub<Output = Self>
187+
+ std::ops::Mul<Output = Self>
188+
+ std::ops::Div<Output = Self>
189+
+ std::ops::Rem<Output = Self>
190+
+ std::ops::AddAssign
191+
+ std::ops::SubAssign
192+
+ std::ops::MulAssign
193+
+ std::ops::DivAssign
194+
+ std::ops::RemAssign
195+
+ std::ops::BitOr<Output = Self>
196+
+ std::ops::BitAnd<Output = Self>
197+
+ std::ops::BitXor<Output = Self>
198+
+ std::ops::BitOrAssign
199+
+ std::ops::BitAndAssign
200+
+ std::ops::BitXorAssign
201+
+ std::ops::Shl<Output = Self>
202+
+ std::ops::Shr<Output = Self>
203+
+ std::ops::ShlAssign
204+
+ std::ops::ShrAssign
205+
+ std::fmt::Display
206+
+ std::fmt::Debug
207+
+ std::fmt::Binary
208+
+ std::fmt::Octal
209+
{
210+
fn zero() -> Self;
211+
}
212+
213+
#[cfg(test)]
214+
mod tests {
215+
use super::*;
216+
217+
impl Number for i64 {
218+
fn zero() -> Self {
219+
0
220+
}
221+
}
222+
223+
#[test]
224+
fn test_min_cost_flow() {
225+
let mut graph = MinCostFlowGraph::new(4);
226+
graph.add_edge(0, 1, 2, 1);
227+
graph.add_edge(0, 2, 1, 2);
228+
graph.add_edge(1, 2, 1, 1);
229+
graph.add_edge(1, 3, 1, 3);
230+
graph.add_edge(2, 3, 2, 1);
231+
let (flow, cost) = graph.flow(0, 3, 2);
232+
assert_eq!(flow, 2);
233+
assert_eq!(cost, 6);
234+
}
235+
}

0 commit comments

Comments
 (0)