1use graph::is_tree;
2
3pub fn tree_diameter(n: usize, edges: &[(usize, usize, u64)]) -> (u64, Vec<usize>) {
5 if n == 0 {
6 return (0, Vec::new());
7 }
8
9 assert!(is_tree(
10 n,
11 &edges
12 .iter()
13 .copied()
14 .map(|(u, v, _)| (u, v))
15 .collect::<Vec<_>>()
16 ));
17
18 for &(_, _, c) in edges {
19 assert!(c >= 1);
20 }
21
22 let mut graph = vec![vec![]; n];
23 for &(u, v, c) in edges {
24 graph[u].push((v, c));
25 graph[v].push((u, c));
26 }
27
28 fn dfs(
29 i: usize,
30 p: usize,
31 g: &[Vec<(usize, u64)>],
32 dist: &mut Vec<u64>,
33 parent: &mut Vec<usize>,
34 ) {
35 parent[i] = p;
36 for &(j, c) in &g[i] {
37 if j == p {
38 continue;
39 }
40 dist[j] = dist[i] + c;
41 dfs(j, i, g, dist, parent);
42 }
43 }
44
45 let mut dist = vec![0; n];
46 let mut parent = vec![0; n];
47 dfs(0, 0, &graph, &mut dist, &mut parent);
48
49 let max_dist = dist.iter().max().copied().unwrap();
50 let s = (0..n).position(|i| dist[i] == max_dist).unwrap();
51 dist = vec![0; n];
52 parent = vec![s; n];
53 dfs(s, s, &graph, &mut dist, &mut parent);
54
55 let diameter = dist.iter().max().copied().unwrap();
56 let t = (0..n).position(|i| dist[i] == diameter).unwrap();
57
58 let mut cur = t;
59 let mut path = Vec::new();
60 path.push(cur);
61 while cur != parent[cur] {
62 cur = parent[cur];
63 path.push(cur);
64 }
65 (diameter, path)
66}
67
68#[cfg(test)]
69mod tests {
70 use super::tree_diameter;
71
72 #[test]
73 fn test_small() {
74 assert_eq!(tree_diameter(0, &[]), (0, vec![]));
75 assert_eq!(tree_diameter(1, &[]), (0, vec![0]));
76
77 let (diameter, path) = tree_diameter(2, &[(0, 1, 1)]);
78 assert_eq!(diameter, 1);
79 assert!(path == vec![0, 1] || path == vec![1, 0]);
80
81 let (diameter, path) = tree_diameter(3, &[(0, 1, 100), (0, 2, 100)]);
82 assert_eq!(diameter, 200);
83 assert!(path == vec![1, 0, 2] || path == vec![2, 0, 1]);
84 }
85}