1use crate::num::one_zero::Zero;
3use crate::tree::*;
4use std::ops::Add;
5
6pub fn tree_distance<E: TreeEdgeTrait>(tr: &Tree<E>, root: usize) -> Vec<E::Weight>
10where
11 E::Weight: Add<Output = E::Weight> + Copy + Zero,
12{
13 let n = tr.len();
14 let mut ret = vec![E::Weight::zero(); n];
15 let mut check = vec![false; n];
16 let mut stack = vec![root];
17
18 while let Some(cur) = stack.pop() {
19 check[cur] = true;
20
21 tr.nodes[cur]
22 .neighbors()
23 .filter(|e| !check[e.to()])
24 .for_each(|e| {
25 ret[e.to()] = ret[cur] + e.weight();
26 stack.push(e.to());
27 });
28 }
29
30 ret
31}
32
33pub fn tree_diameter<E: TreeEdgeTrait>(tr: &Tree<E>) -> (E::Weight, usize, usize)
37where
38 E::Weight: Add<Output = E::Weight> + Copy + Zero + Ord,
39{
40 let a = tree_distance(tr, 0);
41 let (u, _) = a
42 .iter()
43 .enumerate()
44 .max_by(|(_, x), (_, y)| x.cmp(y))
45 .unwrap();
46
47 let b = tree_distance(tr, u);
48 let (v, &d) = b
49 .iter()
50 .enumerate()
51 .max_by(|(_, x), (_, y)| x.cmp(y))
52 .unwrap();
53
54 (d, u, v)
55}
56
57pub fn tree_height<E: TreeEdgeTrait>(tr: &Tree<E>) -> Vec<(E::Weight, usize)>
61where
62 E::Weight: Add<Output = E::Weight> + Copy + Zero + Ord,
63{
64 let d = tree_distance(tr, 0);
65 let (u, _) = d
66 .iter()
67 .enumerate()
68 .max_by(|(_, x), (_, y)| x.cmp(y))
69 .unwrap();
70 let d1 = tree_distance(tr, u);
71 let (v, _) = d1
72 .iter()
73 .enumerate()
74 .max_by(|(_, x), (_, y)| x.cmp(y))
75 .unwrap();
76 let d2 = tree_distance(tr, v);
77
78 d1.into_iter()
79 .zip(d2)
80 .map(|(x, y)| if x > y { (x, u) } else { (y, v) })
81 .collect()
82}
83
84pub fn tree_path<E: TreeEdgeTrait>(tr: &Tree<E>, u: usize, v: usize) -> Vec<usize> {
88 let n = tr.len();
89 let mut ret = vec![];
90 let mut stack = vec![];
91 let mut check = vec![false; n];
92
93 stack.push((u, 0));
94
95 while let Some((i, st)) = stack.pop() {
96 match st {
97 0 => {
98 stack.push((i, 1));
99 ret.push(i);
100
101 if i == v {
102 break;
103 }
104
105 check[i] = true;
106
107 tr.nodes[i]
108 .neighbors()
109 .filter(|e| !check[e.to()])
110 .for_each(|e| stack.push((e.to(), 0)));
111 }
112 1 => {
113 ret.pop();
114 }
115 _ => unreachable!(),
116 }
117 }
118
119 ret
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn test_diameter() {
128 let mut builder = TreeBuilder::new(4);
130 builder.extend(
131 vec![(0, 1, 2), (1, 2, 1), (1, 3, 3)]
132 .into_iter()
133 .map(|(u, v, w)| TreeEdge::new(u, v, w, ())),
134 );
135 let tree = builder.build();
136 assert_eq!(tree_diameter(&tree).0, 5);
137
138 let mut builder = TreeBuilder::new(4);
139 builder.extend(
140 vec![(0, 1, 1), (1, 2, 2), (2, 3, 4)]
141 .into_iter()
142 .map(|(u, v, w)| TreeEdge::new(u, v, w, ())),
143 );
144 let tree = builder.build();
145 assert_eq!(tree_diameter(&tree).0, 7);
146 }
147
148 #[test]
149 fn test_height() {
150 let mut builder = TreeBuilder::new(4);
152 builder.extend(
153 vec![(0, 1, 2), (1, 2, 1), (1, 3, 3)]
154 .into_iter()
155 .map(|(u, v, w)| TreeEdge::new(u, v, w, ())),
156 );
157 let tree = builder.build();
158 assert_eq!(
159 tree_height(&tree)
160 .into_iter()
161 .map(|(x, _)| x)
162 .collect::<Vec<_>>(),
163 [5, 3, 4, 5]
164 );
165 }
166}