zoukankan      html  css  js  c++  java
  • [学习笔记] 虚树

    今天考了个模拟赛,虚树的题我拿(LCT)粗暴卡过,然后被各路神仙疯狂嘲讽,然后就奋发图强,来学了个虚树。

    虚树的概念

    先放一个例题吧:[SDOI 2011]消耗战

    例题单个询问的树形DP可以说是非常简单了,但是多个询问就会(GG),于是我们痛定思痛,发现其实我们并不需要整棵树来转移,我们只需要得到每一个目标节点和他们的(LCA)所构成的树即可,而树的边权即为树上两点在原树上的路径中的最小值。

    那么像这种由目标节点和他们的(LCA)所构成的树即为虚树。

    虚树的构造

    既然知道了啥是虚树,那么就让我们再来看看虚树应该怎么构造吧。

    其实虚树的构造过程类似(dfs)

    我们先整个类似(dfs)的栈,这个栈里存的只有虚树上需要的节点。

    那么对于一个新加入的目标节点 (x)(显然目标节点要按(dfs)序排序再加入),我们分两种情况讨论:

    • (x) 在以(stk[top])为根的子树中

    • (x) 不在以(stk[top])为根的子树中

    第一种情况很简单,直接把 (x) 加入栈即可。

    让我们来具体研究一下第二种情况:

    我们找到次栈顶结点((stak[top-1]))(x)(LCA) ,我们只需要一直把次栈顶与(LCA)比较,若 (dep[stk[top-1]]>dep[LCA]) ,那么便将给栈顶((stk[top]))和次栈顶((stk[top-1]))之间连一条边。

    如果某一时刻(dep[stk[top-1]]<dep[LCA]&&dep[stk[top]]==dep[LCA]),那么就说明(LCA)就是(stk[top]),我们只需要连上((stk[top],x))这条边即可。

    那么如果(dep[stk[top]]>dep[LCA])呢?

    这就说明(LCA)并不在虚树中,我们需要连上((stk[top],LCA)),然后将(LCA)(x) 加入栈中。

    最后,给出建虚树代码:

    void ins(int x){
    	int l=lca(x,stk[top],0);
    	while (top>1&&dep[l]<dep[stk[top-1]]){
    		E[stk[top]].push_back(stk[top-1]);
    		E[stk[top-1]].push_back(stk[top]);
    		--top;
    	}
    	if (dep[stk[top]]>dep[l]){
    	    E[stk[top]].push_back(l);
    	    E[l].push_back(stk[top]);
    	    --top;
    	}
    	if (stk[top]!=l) stk[++top]=l;
    	stk[++top]=x;
    }
    
  • 相关阅读:
    CyclicBarrier与CountDownLatch区别
    导入搜狗实验室新闻语料库
    安装ik分词插件
    分页显示时传递页码的方法
    elasticsearch安装步骤
    linux查看端口占用情况
    Python:文件的读取、创建、追加、删除、清空
    R语言-选择样本数量
    不符合正态分布的配对数据也有自己的统计方法。
    python时间处理
  • 原文地址:https://www.cnblogs.com/WR-Eternity/p/11740574.html
Copyright © 2011-2022 走看看