学习笔记:虚树

\(Warning:\) 全程无图,只是写得能让自己看懂而已,不推荐用此篇入门


何为虚树

把原树的\(k\)个节点提出来建一棵新树,使这棵新树的欧拉序 = 把原树那\(k\)个节点的入/出栈序单独提出来,再sort一遍的顺序,这棵新树就是原树那\(k\)个节点对应的虚树

构建方法

本着先进先出的原则其实只要记录\(dfn\)就可以保证一条链的欧拉序

所以把要构建虚树的点按照\(dfn\)排序,然后用栈维护一条链

假设我们要新加入点\(p\),栈顶为\(x\),栈顶的下一个元素为\(y\)

因为已经按照\(dfn\)排序,所以不会出现\(lca(x,y)==y\)\(lca(x,p)==p\)的情况

如果\(、p、x\)在同一条链,直接把\(p\)入栈

如果\(lca(p,x)!=x\),分情况讨论:

1.\(dfn[y]>dfn[lca(p,x)]\)

​ 连\(y \rightarrow x\)的边,然后将\(x\)出栈

2.\(dfn[y]==dfn[lca(p,x)]\)

​ 即\(y==lca(p,x)\),连\(y \rightarrow x\)的边,然后将\(x\)出栈

3.\(dfn[y]<dfn[lca(p,x)]\)

​ 连\(lca(p,x)\rightarrow x\)的边,保证欧拉序要先把\(x\)出栈,再将\(lca(p,x)\)入栈(相当 于给这条链换了个方向?)

当然最后还是要把\(p\)入栈的

代码:

void insert(int p){
    int ff=lca(p,st[fr]);   
    if(fr==1 || ff==st[fr]){ st[++fr]=p;return; }
    while(fr>1 && dfn[st[fr-1]]>=dfn[ff]) add(st[fr-1],st[fr]),fr--;
    if(ff!=st[fr]) add(ff,st[fr]),st[fr]=ff;
    st[++fr]=p;
}
void build(int num){
    ll tmp=0;
    sort(d+1,d+num+1,cmp);//按dfn从小到大排序
    fr=0,st[++fr]=0;
    for(int i=1;i<=num;++i) insert(d[i]); 
}
应用

优化树形dp

咕咕咕咕咕

转载于:https://www.cnblogs.com/PsychicBoom/p/10638681.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值