competitive/graph/
project_selection_problem.rs1use super::Dinic;
2use std::{cmp::Ordering, collections::HashMap};
3
4#[derive(Debug, Default, Clone)]
5pub struct ProjectSelectionProblem {
6 n_values: Vec<usize>,
7 start: Vec<usize>,
8 cost1: Vec<Vec<i64>>,
9 cost2: HashMap<(usize, usize), u64>,
10 totalcost: i64,
11}
12impl ProjectSelectionProblem {
13 pub fn new(n_project: usize, n_value: usize) -> Self {
14 Self {
15 n_values: vec![n_value; n_project],
16 start: (0..=n_project * (n_value - 1))
17 .step_by(n_value - 1)
18 .collect(),
19 cost1: vec![vec![0i64; n_value]; n_project],
20 cost2: Default::default(),
21 totalcost: 0i64,
22 }
23 }
24 pub fn with_n_values(n_values: Vec<usize>) -> Self {
25 let mut start = Vec::with_capacity(n_values.len() + 1);
26 start.push(0usize);
27 for nv in n_values.iter() {
28 start.push(start.last().unwrap() + nv - 1);
29 }
30 let cost1 = n_values.iter().map(|&n| vec![0i64; n]).collect();
31 Self {
32 n_values,
33 start,
34 cost1,
35 cost2: Default::default(),
36 totalcost: 0i64,
37 }
38 }
39 pub fn add_cost1(&mut self, p: usize, v: usize, c: i64) {
40 self.cost1[p][v] += c;
41 }
42 pub fn add_cost2_01(&mut self, p1: usize, p2: usize, v1: usize, v2: usize, c: u64) {
44 debug_assert!(0 < v1 && v1 < self.n_values[p1]);
45 debug_assert!(0 < v2 && v2 < self.n_values[p2]);
46 let key = (self.start[p1] + v1 - 1, self.start[p2] + v2 - 1);
47 if c > 0 {
48 *self.cost2.entry(key).or_default() += c;
49 }
50 }
51 pub fn add_cost2_10(&mut self, p1: usize, p2: usize, v1: usize, v2: usize, c: u64) {
53 self.add_cost2_01(p2, p1, v2, v1, c);
54 }
55 pub fn add_cost2<F>(&mut self, p1: usize, p2: usize, mut cost: F)
57 where
58 F: FnMut(usize, usize) -> i64,
59 {
60 debug_assert_ne!(p1, p2);
61 let nv1 = self.n_values[p1];
62 let nv2 = self.n_values[p2];
63 debug_assert_ne!(nv1, 0);
64 debug_assert_ne!(nv2, 0);
65 let c00 = cost(0, 0);
66 self.totalcost += c00;
67 for v1 in 1usize..nv1 {
68 self.add_cost1(p1, v1, cost(v1, 0) - c00);
69 }
70 for v2 in 1usize..nv2 {
71 self.add_cost1(p2, v2, cost(0, v2) - c00);
72 }
73 let mut acc = 0i64;
74 for v1 in 1usize..nv1 {
75 for v2 in 1usize..nv2 {
76 let c = cost(v1 - 1, v2) + cost(v1, v2 - 1) - cost(v1, v2) - cost(v1 - 1, v2 - 1);
77 debug_assert!(c >= 0, "cost is not monge");
78 let key = (self.start[p1] + v1 - 1, self.start[p2] + v2 - 1);
79 if c > 0 {
80 *self.cost2.entry(key).or_default() += c as u64;
81 }
82 acc -= c;
83 }
84 self.add_cost1(p1, v1, acc);
85 }
86 }
87 pub fn solve(&self) -> (i64, Vec<usize>) {
88 let vsize = *self.start.last().unwrap();
89 let esize_expect = vsize * 2 + self.cost2.len();
90 let mut builder = Dinic::builder(vsize + 2, esize_expect);
91 let mut totalcost = self.totalcost;
92 let s = vsize;
93 let t = s + 1;
94 for (p, c) in self.cost1.iter().enumerate() {
95 let nv = self.n_values[p];
96 totalcost += c[nv - 1];
97 for v in 1usize..nv {
98 let u = self.start[p] + v - 1;
99 let d = c[v] - c[v - 1];
100 match d.cmp(&0) {
101 Ordering::Less => {
102 builder.add_edge(s, u, (-d) as u64);
103 }
104 Ordering::Greater => {
105 builder.add_edge(u, t, d as u64);
106 totalcost -= d;
107 }
108 Ordering::Equal => {}
109 }
110 if v >= 2 {
111 builder.add_edge(u, u - 1, u64::MAX);
112 }
113 }
114 }
115 for (&(x, y), &c) in self.cost2.iter() {
116 builder.add_edge(x, y, c);
117 }
118 let dgraph = builder.gen_graph();
119 let mut dinic = builder.build(&dgraph);
120 let res = dinic.maximum_flow(s, t) as i64 + totalcost;
121 let visited = dinic.minimum_cut(s);
122 let mut values = vec![0usize; self.n_values.len()];
123 for (p, &nv) in self.n_values.iter().enumerate() {
124 for v in 1usize..nv {
125 values[p] += visited[self.start[p] + v - 1] as usize;
126 }
127 }
128 (res, values)
129 }
130}