虚树

定义

对于一棵树 \(T(S, E)\),取出一个点集 \(T \subseteq S\) 作为关键点集,将关键点和它们两两的 LCA 取出构成一个点集 \(V'\) 建一棵树,即为虚树。

建树

  • \(S\) 中所有点按 DFS 序排序,把所有相邻项的 LCA 再求出来放入序列 \(A\)。根据 DFS 序的性质,此时将 \(A\) 去重就得到了虚树的点集。
  • 然后将序列 \(A\) 排序,对 \(A\) 中所有 \((A_i, A_{i+1})\),将它们的 LCA 记录为父亲节点即可。
inline bool cmp(int x, int y)
{
	return dfn[x] < dfn[y];  // 按照 dfs 序排序
}

void build_virtual_tree()
{
	sort(h + 1, h + m + 1, cmp);  // 把关键点按照 dfs 序排序
	for(int i = 1; i < m; i++){
		a[++len] = h[i];
		a[++len] = lca(h[i], h[i + 1]);  // 插入 lca
	}
	a[++len] = h[m];
	sort(a + 1, a + len + 1, cmp);  // 把所有虚树上的点按照 dfs 序排序
	len = unique(a + 1, a + len + 1) - a - 1;  // 去重
	for(int i = 1, lc; i < len; ++i) {
		lc = lca(a[i], a[i + 1]);
		fa[a[i]] = fa[a[i + 1]] = lc;
	}
}
posted @ 2025-07-22 11:06  心灵震荡  阅读(9)  评论(0)    收藏  举报