Skip to content

Commit 0312d8d

Browse files
authored
Merge pull request #25 from kenkoooo/features/mincostflow
Implement mincostflow
2 parents 897c6fd + 9c36e0c commit 0312d8d

File tree

3 files changed

+202
-1
lines changed

3 files changed

+202
-1
lines changed

src/internal_type_traits.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use std::{
1919
//
2020
// Maybe we should rename this to `PrimitiveInteger` or something, as it probably won't be used in the
2121
// same way as the original ACL.
22-
pub(crate) trait Integral:
22+
pub trait Integral:
2323
'static
2424
+ Send
2525
+ Sync

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub(crate) mod internal_type_traits;
2020

2121
pub use dsu::Dsu;
2222
pub use fenwicktree::FenwickTree;
23+
pub use mincostflow::MinCostFlowGraph;
2324
pub use string::{
2425
lcp_array, lcp_array_arbitrary, suffix_array, suffix_array_arbitrary, suffix_array_manual,
2526
z_algorithm, z_algorithm_arbitrary,

src/mincostflow.rs

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,201 @@
1+
use crate::internal_type_traits::Integral;
12

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

Comments
 (0)