zoukankan      html  css  js  c++  java
  • 倍增求lca

    /*
    节点维护的信息多样
    如果用树状数组维护到根节点的边权或者点权, 可以直接插入点权和边权值,不需要预处理,
    但是记得一定要使用ot[]消除影响.即差分.    Housewife Wind  这个坑踩得死死得.
    然后如果带修改,也可以线段树维护.  
    打上dfs序后, 其他的就是区间问题了. 然后查询 修改的时候,把dfs序与点或者边对应转换一下就OK了. 
    */ 
    int deep[maxn];
    int up[maxn][24];
    int   in[maxn];  // dfs序 入 
    int   ot[maxn];  // dfs序 出 
    int   pa[maxn];  // father 数组 
    int qsz, qtot;
    
    // 预处理出 deep[] in[] ot[] pa[] up[i][0] 
    void dfs(int u, int fa)
    {
        int i, v;
        deep[u] = deep[fa] + 1;
        in[u] = qtot;
        for (i=head[u]; i; i=edge[i].lst) {
            v = edge[i].to;
            if (v == fa) continue;
            up[v][0] = u;
            pa[v] = u;
            ++qtot;  // dfs序标号用. 
            dfs(v, u);
        }
        ot[u] = qtot;
    }
    
    // 获取公共祖先的表. 
    void GetUp(int n)
    {
        int i, j;
        for (j=1; j<20; ++j) 
            for (i=1; i<=n; ++i) 
                up[i][j] = up[up[i][j-1]][j-1];
    }
    
    // 倍增求lca 
    int lca(int u, int v)
    {
        if (deep[u] < deep[v]) swap(u, v);
        int i, j, k = deep[u] - deep[v];
        for (i=0; i<20; ++i) // 获取第k个祖先 
            if ((1<<i) & k) 
                u = up[u][i];
        if (u != v) {
            for (i=20; i>=0; --i) 
                if (up[u][i] != up[v][i]) {
                    u = up[u][i];
                    v = up[v][i];
                }
            u = up[u][0];
        }
        return u;
    }
    
    int main()
    {
        // 多Cas记得清零 up[][] 之类的数组  还有全局变量 
        deep[0] = 0;
        dfs(1, 0);
        GetUp(n);  // 在dfs()预处理出各节点的父亲后调用. 
        
        return 0;
    }

     至于求解答案的几种, 一般也就那几种, 根据维护的信息来画个图,看怎么求解答案. 

  • 相关阅读:
    JS---案例:拖曳对话框
    关于选用ccflow你所担心的问题都在这里为您解答
    Elasticsearch(GEO)数据写入和空间检索
    echart的legend不显示问题
    html5+css3的神奇搭配
    h5+css3+Jq
    初探 jQuery
    在vi编辑器中如何向上翻页,向下翻页以及查询“ab”
    webpack4 特性
    webpack4配置
  • 原文地址:https://www.cnblogs.com/cgjh/p/9491332.html
Copyright © 2011-2022 走看看