基于子树气泡动态收缩判定重心性质,并双重深度遍历(Two-DFS)流光绘制树的最长直径路径
在无环连通图——树(Tree)中,重心和直径是其最核心的两个拓扑几何量:
重心是树上的一个节点 $u$,满足删去 $u$ 后,分裂出的所有子树中最大子树的大小最小。
max_size[i] = max(N - size[i], max(size[children]))。全局遍历求出该值最小的节点即为重心。直径是树中任意两个节点之间最长简单路径的长度。
// 1. 树的重心求解:最大子树极小化
int sz[MAXN], max_part[MAXN], centroid = 0;
void getCentroid(int u, int p) {
sz[u] = 1;
max_part[u] = 0;
for (int v : g[u]) {
if (v == p) continue;
getCentroid(v, u);
sz[u] += sz[v];
max_part[u] = max(max_part[u], sz[v]); // 子节点子树最大值
}
// 上方父节点连通块大小 n - sz[u]
max_part[u] = max(max_part[u], n - sz[u]);
if (centroid == 0 || max_part[u] < max_part[centroid]) {
centroid = u; // 极小化重心
}
}