【模板】虚树

虚树就是把关键的点从原树中抠出来,再把它们的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--;
    }
posted @ 2020-07-16 14:40  LawrenceD  阅读(86)  评论(0)    收藏  举报