Eccentricity
$ecc(u)$ = the longest distance from $u$ in the tree = the larger of $d(u, s), d(u, t)$ where $s$ to $t$ is a diameter.
$$ \begin{align} &ecc(u) = \max_{v \in V} d(u, v) = max(d(u, s), d(u, t)) \end{align} $$
Diameter is the maximum eccentricity, that is, the longest distance in the tree.
$$ d = \max_{u \in V} ecc(u) = \max_{u \in V} \max_{v \in V} d(u, v) $$
Radius is the minimum eccentricity in the tree.
$$ r = \min_{u \in V} ecc(u) = \min_{u \in V} \max_{v \in V} d(u, v) $$
The center(s) is the vertices $u$ that has $ecc(u) = r$.
To find $s, t$, we can perform 2 BFS:
// Find s, t
let dep_from_0 = bfs(&adj, 0, usize::MAX);
let s = (0..n).max_by_key(|u| dep_from_0[u]).unwrap();
let dep_from_s = bfs(&adj, s, usize::MAX);
let t = (0..n).max_by_key(|u| dep_from_s[u]).unwrap();
let diamter = dep_from_s[t];
// Build ecc
let dep_from_t = bfs(&adj, t);
let ecc: Vec<usize> = (0..n).map(|u| dep_from_s[u].max(dep_from_t[u])).collect();
let diameter = ecc.iter().max().unwrap();
let radius = ecc.iter().min().unwrap();
fn bfs<T>(adj: &Vec<Vec<(usize, T)>>, s: usize, inf: T) -> (Vec<T>, Vec<usize>)
where
T: std::ops::Add<Output = T> + Ord + Default + Copy,
{
let n = adj.len();
let mut que = VecDeque::new();
let mut dis = vec![inf; n];
let mut par = vec![!0; n];
dis[s] = T::default();
par[s] = s;
que.push_back(s);
while let Some(u) = que.pop_front() {
for &(v, w) in adj[u].iter() {
if dis[v] == inf {
dis[v] = dis[u] + w;
par[v] = u;
que.push_back(v);
}
}
}
(dis, par)
}
These concepts can be extended to weighted tree.