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

    文章来自:https://blog.sengxian.com/algorithms/virtual-tree

    本文由于格式问题,插图需要重新打开来看。

    概述

    在 OI 比赛中,有这样一类题目:给定一棵树,另有多次询问,每个询问给定一些关键点,需要求这些关键点之间的某些信息。询问数可能很多,但满足所有询问中关键点数量的总和与树的大小同阶。

    由于询问数可以非常多,每次无法遍历整棵树,这类题目看似没有办法做,但实际上,我们可以用一种叫做虚树(virtual tree)的技术来解决这一问题。

    介绍

    简单来说,虚树是对一颗有根树中的一些关键点而言的,虚树将树的大小压缩到与关键点的数量同阶。虚树中包含了所有的关键点,也包含了所有关键点两两之间的 LCA(lowest common ancestor, 最近公共祖先)(LCA 的数量不超过关键点的个数,稍后有证明),这就保证了虚树不会丧失原有的树形结构,同时尽可能地压缩了树的大小。同时虚树中 u 到 v 的边权定义为原树中 u到 v 的最短路径。

    我们看一个虚树的例子(黑色点为关键点,红色点为 LCA):

     

      代码:

    inline bool cmp(const int &i, const int &j) {
        return dfn[i] < dfn[j];
    }
    
    void build(int vectrices[], int k) {
        static int stk[MAX_N];
        sort(vectrices, vectrices + k, cmp);
    
        stk[sz++] = 0;
        for (int i = 0; i < k; ++i) {
            int u = vectrices[i], lca = ::lca(u, stk[sz - 1]);
            if (lca == stk[sz - 1]) stk[sz++] = u;
            else {
                while (sz - 2 >= 0 && dep[stk[sz - 2]] >= dep[lca]) {
                    addEdge(stk[sz - 2], stk[sz - 1]);
                    sz--;
                }
    
                if (stk[sz - 1] != lca) {
                    addEdge(lca, stk[--sz]);
                    stk[sz++] = lca, vectrices[cnt++] = lca;
                }
    
                stk[sz++] = u;
            }
        }
        for (int i = 0; i < sz - 1; ++i) addEdge(stk[i], stk[i + 1]);
    

      例题:BZOJ 2286
    BZOJ 3572
    BZOJ 3991

  • 相关阅读:
    docker run 参数含义
    java——数组队列 ArrayQueue
    java——数组栈 ArrayStack
    java——时间复杂度、动态数组
    java——异常类、异常捕获、finally、异常抛出、自定义异常
    java——变量
    java——虚拟机、线程
    java——内部类
    java——object类
    java——抽象类、接口、二者区别
  • 原文地址:https://www.cnblogs.com/mybing/p/8456817.html
Copyright © 2011-2022 走看看