【模板】虚树
虚树就是把关键的点从原树中抠出来,再把它们的lca拿出来,建成的一棵树。
一般是对虚树进行dp
这里主要讲怎么构建(怕自己忘记)
把虚树上关键节点按照dfs序排序
首先开一个栈,栈中存储一条链,表示加入虚树从上到下的一条链
要拿当前加入的节点与栈顶节点进行比较。求lca记为z
假如当前栈中栈顶的上一个元素(有点绕哈,就是栈中第二深的点)的深度比当前z的深度要大
那么我们肯定可以删出栈顶(不直接和栈顶比较是为了方便加边)
此时加入一条栈顶的上一个元素和栈顶的边
如果栈中只有一个元素或者不满足上述条件就停止
然后再拿栈顶和z比较深度,如果栈顶深度比z大,这样x肯定不再在栈顶所在子树中,把栈顶弹掉并加边
这样一来栈要么是空的,要么栈顶元素深度<=z的深度。如果不等于的话直接加入z就好
这时直接加入x,肯定不和z相同,否则就会加过了。 记得最后要弹栈
代码如下:
sort(nd + 1, nd + 1 + tot, cmp);
zh[++tp] = nd[1];
int RT = nd[1];
for(int i = 2;i <= tot; i++){
int x = nd[i], z = lca(x, zh[tp]);
if(dep[z] < dep[RT])RT = z;
while(tp > 1 && dep[z] < dep[zh[tp-1]]){
G.add(zh[tp-1], zh[tp], dis1[zh[tp]] - dis1[zh[tp-1]]);
tp--;
}
if(tp && dep[zh[tp]] > dep[z]){
G.add(z, zh[tp], dis1[zh[tp]] - dis1[z]);
tp--;
}
if(!tp || zh[tp] != z)zh[++tp] = z;
zh[++tp] = x;
}
while(tp > 1){
G.add(zh[tp-1], zh[tp], dis1[zh[tp]] - dis1[zh[tp-1]]);
tp--;
}