虚树

用以解决树上的和点集相关的问题,将树的大小缩减至 \(\mathcal{O}(|S|)\) 级别。

构建方法即将所有关键点按照 \(\rm dfs\) 序排序,然后再将 \(LCA(s_i,s_{i+1})\) 加入并去重,时间复杂度 \(\mathcal{O}(n\log n)\)

有线性构建的单调栈方法,没学。

粘个代码

for(int i=1; i<=k; i++)
{
    if(a[i]==1) continue;
    int lca=LCA(sta[top],a[i]);
    if(lca!=sta[top])
    {
        while(dfn[lca]<dfn[sta[top-1]])
            g[sta[top-1]].push_back(sta[top]), top--;
        g[lca].push_back(sta[top]);
        if(dfn[lca]>dfn[sta[top-1]]) sta[top]=lca;
        else top--;
    }
    sta[++top]=a[i];
}
for(int i=1; i<top; i++)
    g[sta[i]].push_back(sta[i+1]);

一些性质

  • 点集 \(S=\{u_0,u_1,\dots,d_{m-1}\}\) 的完整虚树的边权和:

    \[\dfrac{1}{2}\sum\limits_{i=0}^{m-1}dis(u_i,u_{(i+1)\bmod m}) \]

    应用:P3320 [SDOI2015] 寻宝游戏

简单题:

posted @ 2024-09-11 11:42  xishanmeigao  阅读(5)  评论(0编辑  收藏  举报