zoukankan      html  css  js  c++  java
  • 树上倍增与LCA

    找i节点的第k个父亲

    int father(int i,int k)
    {
        for(int x=0;x<=int(log2(k));x++)
            if((1<<x)&k)    //(1<<x)&k可以判断k的二进制表示中,第(x-1)位上是否为1
                i=fa[i][x];     //把i往上提
        return i;
    }
    4

    预处理fa数组

    void dfs(int x)
    {
        for(int i=1;i<=max0;i++)
            if(fa[x][i-1])   //在dfs(x)之前,x的父辈们的fa数组都已经计算完毕,所以可以用来计算x
                fa[x][i]=fa[fa[x][i-1]][i-1];
            else break;    //如果x已经没有第2^(i-1)个父亲了,那么也不会有更远的父亲,直接break
        for(/*每一个与x相连的节点i*/)
            if(i!=fa[x][0])     //如果i不是x的父亲就是x的儿子
            {
                fa[i][0]=x;       //记录儿子的第一个父亲是x
                dep[i]=dep[x]+1;      //处理深度
                dfs(i);
            }
    }

    LCA

    int LCA(int u,int v)
    {
        if(dep[u]<dep[v])swap(u,v);  //我们默认u的深度一开始大于v,那么如果u的深度小就交换u和v
        int delta=dep[u]-dep[v];    //计算深度差
        for(int x=0;x<=max0;x++)    //此循环用于提到深度相同。
            if((1<<x)&delta)
                u=fa[u][x];
        if(u==v)return u;
        for(int x=max0;x>=0;x--)     //注意!此处循环必须是从大到小!因为我们应该越提越“精确”,
            if(fa[u][x]!=fa[v][x])   //如果从小到大的话就有可能无法提到正确位置,自己可以多想一下
            {
                u=fa[u][x];
                v=fa[v][x];
            }
        return fa[u][0];    //此时u、v的第一个父亲就是LCA。
    }
    rush!
  • 相关阅读:
    点灯
    流水灯
    <<晨间日记>>要点
    PL/SQL 函数学习 Start with...Connect By
    FTP Put步骤回顾
    ORA16038,ORA19809,ORA00312无法归档的解决方法
    Emacs for windows
    ORA01578,ORA01115,ORA01110 ORACLE 数据块损坏
    MySQL存储过程的调优过程
    ORA01110 数据文件日志文件丢失打不开数据库
  • 原文地址:https://www.cnblogs.com/LH2000/p/15045071.html
Copyright © 2011-2022 走看看