haar_lib/graph/
chinese_postman.rs1#![allow(clippy::needless_range_loop)]
4
5use crate::graph::*;
6use crate::num::one_zero::Zero;
7use std::ops::Add;
8
9pub fn chinese_postman_problem<E: EdgeTrait>(g: &Graph<Undirected, E>) -> E::Weight
11where
12 E::Weight: Copy + Ord + Add<Output = E::Weight> + Zero,
13{
14 let n = g.len();
15 let zero = E::Weight::zero();
16
17 let mut dist = vec![vec![None; n]; n];
18
19 for i in 0..n {
20 dist[i][i] = Some(zero);
21 }
22
23 for e in g.nodes_iter().flat_map(|v| &v.edges) {
24 let (from, to, cost) = (e.from(), e.to(), e.weight());
25 dist[from][to] = dist[from][to].map(|x| x.min(cost)).or(Some(cost));
26 }
27
28 for k in 0..n {
29 for i in 0..n {
30 for j in 0..n {
31 if let (Some(x), Some(y)) = (dist[i][k], dist[k][j]) {
32 dist[i][j] = dist[i][j].map(|z| z.min(x + y)).or(Some(x + y))
33 }
34 }
35 }
36 }
37
38 let odd: Vec<_> = g
39 .nodes_iter()
40 .enumerate()
41 .filter_map(|(i, es)| (es.edges.len() % 2 == 1).then_some(i))
42 .collect();
43 let m = odd.len();
44
45 let mut dp = vec![None; 1 << m];
46 dp[0] = Some(zero);
47
48 for i in 0..1 << m {
49 for j in 0..m {
50 for k in 0..j {
51 if (i & (1 << j)) == 0 || (i & (1 << k)) == 0 {
52 continue;
53 }
54
55 if let Some(d) = dp[i ^ (1 << j) ^ (1 << k)] {
56 let d = d + dist[odd[j]][odd[k]].unwrap();
57 dp[i] = dp[i].map(|x| x.min(d)).or(Some(d));
58 }
59 }
60 }
61 }
62
63 g.nodes_iter()
64 .flat_map(|es| {
65 es.edges
66 .iter()
67 .filter_map(|e| (e.from() <= e.to()).then_some(e.weight()))
68 })
69 .fold(dp[(1 << m) - 1].unwrap(), |x, y| x + y)
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn test() {
78 let mut g = Graph::<Undirected, _>::new(4);
80 g.extend(
81 vec![(0, 1, 1), (0, 2, 2), (1, 3, 3), (2, 3, 4)]
82 .into_iter()
83 .map(|(u, v, w)| Edge::new(u, v, w, ())),
84 );
85 assert_eq!(chinese_postman_problem(&g), 10);
86
87 let mut g = Graph::<Undirected, _>::new(4);
88 g.extend(
89 vec![(0, 1, 1), (0, 2, 2), (1, 3, 3), (2, 3, 4), (1, 2, 5)]
90 .into_iter()
91 .map(|(u, v, w)| Edge::new(u, v, w, ())),
92 );
93 assert_eq!(chinese_postman_problem(&g), 18);
94
95 let mut g = Graph::<Undirected, _>::new(2);
96 g.extend(
97 vec![(0, 1, 1), (0, 1, 2), (0, 1, 3)]
98 .into_iter()
99 .map(|(u, v, w)| Edge::new(u, v, w, ())),
100 );
101 assert_eq!(chinese_postman_problem(&g), 7);
102 }
103}