vector< int > adj[maxn]; int fa[maxn], dep[maxn], sz[maxn], son[maxn]; // DFS1 维护信息 int top[maxn]; // DFS2 维护链顶 int n, m, root;
// DFS 1: 计算子树大小、深度、父节点、重儿子 voiddfs1( int u, int p ) { dep[u] = dep[p] + 1; fa[u] = p; sz[u] = 1; for( int v : adj[u] ) { if( v == p ) continue; dfs1( v, u ); sz[u] += sz[v]; if( sz[v] > sz[son[u]] ) son[u] = v; } }
// DFS 2: 建立重链,记录 top // u: 当前节点, t: 当前链的顶端 voiddfs2( int u, int t ) { top[u] = t;
// 优先处理重儿子,延续重链 if( son[u] ) dfs2( son[u], t );
// 处理轻儿子,轻儿子是新链的开端 for( int v : adj[u] ) { if( v == fa[u] || v == son[u] ) continue; dfs2( v, v ); // 轻儿子自己就是新链的 top } }
// HLD 查询 LCA: 类似“跳链” intget_lca( int u, int v ) { // 如果 u 和 v 不在同一条链上,就往上跳 while( top[u] != top[v] ) { // 谁的链顶深度大,谁往上跳 if( dep[top[u]] < dep[top[v]] ) swap( u, v );