competitive/tree/
tree_center.rs1use crate::graph::UndirectedSparseGraph;
2
3#[codesnip::entry("tree_center")]
4#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
5pub enum TreeCenter {
6 One(usize),
7 Two(usize, usize),
8}
9#[codesnip::entry("tree_center", include("SparseGraph"))]
10impl UndirectedSparseGraph {
11 pub fn tree_center(&self) -> TreeCenter {
13 let n = self.vertices_size();
14 assert_ne!(n, 0);
15 let mut deq = std::collections::VecDeque::with_capacity(n);
16 let mut deg: Vec<_> = self.vertices().map(|u| self.adjacencies(u).len()).collect();
17 for u in self.vertices() {
18 if self.adjacencies(u).len() <= 1 {
19 deq.push_back(u);
20 }
21 }
22 let mut k = 0;
23 let mut cnt = deq.len();
24 if cnt < n {
25 k = deq.len();
26 'outer: while let Some(u) = deq.pop_front() {
27 k -= 1;
28 for a in self.adjacencies(u) {
29 deg[a.to] -= 1;
30 if deg[a.to] == 1 {
31 deq.push_back(a.to);
32 cnt += 1;
33 if cnt == n {
34 break 'outer;
35 }
36 }
37 }
38 if k == 0 {
39 k = deq.len();
40 }
41 }
42 }
43 if deq.len() == k + 1 {
44 TreeCenter::One(*deq.back().unwrap())
45 } else {
46 let u = deq.pop_back().unwrap();
47 let v = deq.pop_back().unwrap();
48 if u < v {
49 TreeCenter::Two(u, v)
50 } else {
51 TreeCenter::Two(v, u)
52 }
53 }
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use crate::{graph::UndirectedSparseGraph, tools::Xorshift, tree::MixedTree};
61
62 impl UndirectedSparseGraph {
63 fn naive_tree_center(&self) -> TreeCenter {
64 let mut md: Vec<_> = self
65 .vertices()
66 .map(|u| (self.tree_depth(u).into_iter().max().unwrap_or_default(), u))
67 .collect();
68 md.sort_unstable();
69 if md.len() == 1 {
70 TreeCenter::One(md[0].1)
71 } else if md.len() >= 2 {
72 if md[0].0 == md[1].0 {
73 TreeCenter::Two(md[0].1, md[1].1)
74 } else {
75 TreeCenter::One(md[0].1)
76 }
77 } else {
78 panic!("vertex size should be larger than one.");
79 }
80 }
81 }
82
83 #[test]
84 fn test_center_handmaid() {
85 assert_eq!(
86 UndirectedSparseGraph::from_edges(1, vec![]).tree_center(),
87 TreeCenter::One(0)
88 );
89 assert_eq!(
90 UndirectedSparseGraph::from_edges(2, vec![(0, 1)]).tree_center(),
91 TreeCenter::Two(0, 1)
92 );
93 assert_eq!(
94 UndirectedSparseGraph::from_edges(3, vec![(0, 1), (0, 2)]).tree_center(),
95 TreeCenter::One(0)
96 );
97 assert_eq!(
98 UndirectedSparseGraph::from_edges(4, vec![(0, 1), (1, 2), (1, 3)]).tree_center(),
99 TreeCenter::One(1)
100 );
101 assert_eq!(
102 UndirectedSparseGraph::from_edges(5, vec![(0, 1), (1, 2), (1, 3), (3, 4)])
103 .tree_center(),
104 TreeCenter::Two(1, 3)
105 );
106 assert_eq!(
107 UndirectedSparseGraph::from_edges(
108 7,
109 vec![(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
110 )
111 .tree_center(),
112 TreeCenter::One(3)
113 );
114 }
115
116 #[test]
117 fn test_center_random() {
118 let mut rng = Xorshift::default();
119 const N: usize = 200;
120 const Q: usize = 200;
121 for _ in 0..Q {
122 let n = rng.random(1..=N);
123 let g = rng.random(MixedTree(n));
124 assert_eq!(g.tree_center(), g.naive_tree_center());
125 }
126 }
127}