contest_algorithms/graph/
flow.rs

1//! Maximum flows, matchings, and minimum cuts.
2use super::{AdjListIterator, Graph};
3
4/// Representation of a network flow problem with (optional) costs.
5pub struct FlowGraph {
6    /// Owned graph, managed by this FlowGraph object.
7    pub graph: Graph,
8    /// Edge capacities.
9    pub cap: Vec<i64>,
10    /// Edge cost per unit flow.
11    pub cost: Vec<i64>,
12}
13
14impl FlowGraph {
15    /// An upper limit to the flow.
16    const INF: i64 = 0x3f3f_3f3f_3f3f_3f3f;
17
18    /// Initializes an flow network with vmax vertices and no edges.
19    pub fn new(vmax: usize, emax_hint: usize) -> Self {
20        Self {
21            graph: Graph::new(vmax, 2 * emax_hint),
22            cap: Vec::with_capacity(2 * emax_hint),
23            cost: Vec::with_capacity(2 * emax_hint),
24        }
25    }
26
27    /// Adds an edge with specified directional capacities and cost per unit of
28    /// flow. If only forward flow is allowed, rcap should be zero.
29    pub fn add_edge(&mut self, u: usize, v: usize, cap: i64, rcap: i64, cost: i64) {
30        self.cap.push(cap);
31        self.cap.push(rcap);
32        self.cost.push(cost);
33        self.cost.push(-cost);
34        self.graph.add_undirected_edge(u, v);
35    }
36
37    /// Dinic's algorithm to find the maximum flow from s to t where s != t.
38    /// Generalizes the Hopcroft-Karp maximum bipartite matching algorithm.
39    /// V^2E in general, min(V^(2/3),sqrt(E))E when all edges are unit capacity,
40    /// sqrt(V)E when all vertices are unit capacity as in bipartite graphs.
41    ///
42    /// # Panics
43    ///
44    /// Panics if the maximum flow is 2^63 or larger.
45    pub fn dinic(&self, s: usize, t: usize) -> (i64, Vec<i64>) {
46        let mut flow = vec![0; self.graph.num_e()];
47        let mut max_flow = 0;
48        loop {
49            let dist = self.dinic_search(s, &flow);
50            if dist[t] == Self::INF {
51                break;
52            }
53            // Keep track of adjacency lists to avoid revisiting blocked edges.
54            let mut adj_iters = (0..self.graph.num_v())
55                .map(|u| self.graph.adj_list(u).peekable())
56                .collect::<Vec<_>>();
57            max_flow += self.dinic_augment(s, t, Self::INF, &dist, &mut adj_iters, &mut flow);
58        }
59        (max_flow, flow)
60    }
61
62    // Compute BFS distances to restrict attention to shortest path edges.
63    fn dinic_search(&self, s: usize, flow: &[i64]) -> Vec<i64> {
64        let mut dist = vec![Self::INF; self.graph.num_v()];
65        let mut q = ::std::collections::VecDeque::new();
66        dist[s] = 0;
67        q.push_back(s);
68        while let Some(u) = q.pop_front() {
69            for (e, v) in self.graph.adj_list(u) {
70                if dist[v] == Self::INF && flow[e] < self.cap[e] {
71                    dist[v] = dist[u] + 1;
72                    q.push_back(v);
73                }
74            }
75        }
76        dist
77    }
78
79    // Pushes a blocking flow that increases the residual's s-t distance.
80    fn dinic_augment(
81        &self,
82        u: usize,
83        t: usize,
84        f: i64,
85        dist: &[i64],
86        adj: &mut [::std::iter::Peekable<AdjListIterator>],
87        flow: &mut [i64],
88    ) -> i64 {
89        if u == t {
90            return f;
91        }
92        let mut df = 0;
93
94        while let Some(&(e, v)) = adj[u].peek() {
95            let rem_cap = (self.cap[e] - flow[e]).min(f - df);
96            if rem_cap > 0 && dist[v] == dist[u] + 1 {
97                let cf = self.dinic_augment(v, t, rem_cap, dist, adj, flow);
98                flow[e] += cf;
99                flow[e ^ 1] -= cf;
100                df += cf;
101                if df == f {
102                    break;
103                }
104            }
105            // The current edge is either saturated or blocked.
106            adj[u].next();
107        }
108        df
109    }
110
111    /// After running maximum flow, use this to recover the dual minimum cut.
112    pub fn min_cut(&self, dist: &[i64]) -> Vec<usize> {
113        (0..self.graph.num_e())
114            .filter(|&e| {
115                let u = self.graph.endp[e ^ 1];
116                let v = self.graph.endp[e];
117                dist[u] < Self::INF && dist[v] == Self::INF
118            })
119            .collect()
120    }
121
122    /// Among all s-t maximum flows, finds one with minimum cost, assuming
123    /// s != t and no negative-cost cycles.
124    ///
125    /// # Panics
126    ///
127    /// Panics if the flow or cost overflow a 64-bit signed integer.
128    pub fn mcf(&self, s: usize, t: usize) -> (i64, i64, Vec<i64>) {
129        let mut pot = vec![0; self.graph.num_v()];
130
131        // Bellman-Ford deals with negative-cost edges at initialization.
132        for _ in 1..self.graph.num_v() {
133            for e in 0..self.graph.num_e() {
134                if self.cap[e] > 0 {
135                    let u = self.graph.endp[e ^ 1];
136                    let v = self.graph.endp[e];
137                    pot[v] = pot[v].min(pot[u] + self.cost[e]);
138                }
139            }
140        }
141
142        let mut flow = vec![0; self.graph.num_e()];
143        let (mut min_cost, mut max_flow) = (0, 0);
144        loop {
145            let par = self.mcf_search(s, &flow, &mut pot);
146            if par[t] == None {
147                break;
148            }
149            let (dc, df) = self.mcf_augment(t, &par, &mut flow);
150            min_cost += dc;
151            max_flow += df;
152        }
153        (min_cost, max_flow, flow)
154    }
155
156    // Maintains Johnson's potentials to prevent negative-cost residual edges.
157    // This allows running Dijkstra instead of the slower Bellman-Ford.
158    fn mcf_search(&self, s: usize, flow: &[i64], pot: &mut [i64]) -> Vec<Option<usize>> {
159        let mut vis = vec![false; self.graph.num_v()];
160        let mut dist = vec![Self::INF; self.graph.num_v()];
161        let mut par = vec![None; self.graph.num_v()];
162
163        dist[s] = 0;
164        while let Some(u) = (0..self.graph.num_v())
165            .filter(|&u| !vis[u] && dist[u] < Self::INF)
166            .min_by_key(|&u| dist[u] - pot[u])
167        {
168            vis[u] = true;
169            pot[u] = dist[u];
170            for (e, v) in self.graph.adj_list(u) {
171                if dist[v] > dist[u] + self.cost[e] && flow[e] < self.cap[e] {
172                    dist[v] = dist[u] + self.cost[e];
173                    par[v] = Some(e);
174                }
175            }
176        }
177        par
178    }
179
180    // Pushes flow along an augmenting path of minimum cost.
181    fn mcf_augment(&self, t: usize, par: &[Option<usize>], flow: &mut [i64]) -> (i64, i64) {
182        let (mut dc, mut df) = (0, Self::INF);
183        let mut u = t;
184        while let Some(e) = par[u] {
185            df = df.min(self.cap[e] - flow[e]);
186            u = self.graph.endp[e ^ 1];
187        }
188        u = t;
189        while let Some(e) = par[u] {
190            flow[e] += df;
191            flow[e ^ 1] -= df;
192            dc += df * self.cost[e];
193            u = self.graph.endp[e ^ 1];
194        }
195        (dc, df)
196    }
197}
198
199#[cfg(test)]
200mod test {
201    use super::*;
202
203    #[test]
204    fn test_basic_flow() {
205        let mut graph = FlowGraph::new(3, 2);
206        graph.add_edge(0, 1, 4, 0, 0);
207        graph.add_edge(1, 2, 3, 0, 0);
208
209        let flow = graph.dinic(0, 2).0;
210        assert_eq!(flow, 3);
211    }
212
213    #[test]
214    fn test_min_cost_flow() {
215        let mut graph = FlowGraph::new(4, 4);
216        graph.add_edge(0, 1, 10, 0, -10);
217        graph.add_edge(1, 2, 7, 0, 8);
218        graph.add_edge(2, 3, 7, 0, 8);
219        graph.add_edge(1, 3, 7, 0, 10);
220
221        let (cost, flow, _) = graph.mcf(0, 3);
222        assert_eq!(cost, 18);
223        assert_eq!(flow, 10);
224    }
225
226    #[test]
227    fn test_max_matching() {
228        let mut graph = FlowGraph::new(14, 4);
229
230        let source = 0;
231        let sink = 13;
232
233        //Vertex indices of "left hand side" of bipartite graph go from [left_start, right_start)
234        let left_start = 1;
235        //Vertex indices of "right hand side" of bipartite graph go from [right_start, sink)
236        let right_start = 7;
237
238        //Initialize source / sink connections; both left & right have 6 nodes
239        for lhs_vertex in left_start..left_start + 6 {
240            graph.add_edge(source, lhs_vertex, 1, 0, 0);
241        }
242
243        for rhs_vertex in right_start..right_start + 6 {
244            graph.add_edge(rhs_vertex, sink, 1, 0, 0);
245        }
246
247        graph.add_edge(left_start + 0, right_start + 1, 1, 0, 0);
248        graph.add_edge(left_start + 0, right_start + 2, 1, 0, 0);
249        graph.add_edge(left_start + 2, right_start + 0, 1, 0, 0);
250        graph.add_edge(left_start + 2, right_start + 3, 1, 0, 0);
251        graph.add_edge(left_start + 3, right_start + 2, 1, 0, 0);
252        graph.add_edge(left_start + 4, right_start + 2, 1, 0, 0);
253        graph.add_edge(left_start + 4, right_start + 3, 1, 0, 0);
254        graph.add_edge(left_start + 5, right_start + 5, 1, 0, 0);
255
256        let (flow_amt, flow) = graph.dinic(source, sink);
257        assert_eq!(flow_amt, 5);
258
259        //L->R edges in maximum matching
260        let left_right_edges = flow
261            .into_iter()
262            .enumerate()
263            .filter(|&(_e, f)| f > 0)
264            //map to u->v
265            .map(|(e, _f)| (graph.graph.endp[e ^ 1], graph.graph.endp[e]))
266            //leave out source and sink nodes
267            .filter(|&(u, v)| u != source && v != sink)
268            .collect::<Vec<_>>();
269
270        assert_eq!(
271            left_right_edges,
272            vec![(1, 8), (3, 7), (4, 9), (5, 10), (6, 12)]
273        );
274    }
275}