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!
  • 相关阅读:
    单点登录实现机制
    简单工厂
    单例模式
    Remoting
    Redis编码问题
    减少手机页面跳转的方法(转)
    失血模型,充血模型
    Hashtable
    Why we don’t recommend using List<T> in public APIs
    Aggregate累加器
  • 原文地址:https://www.cnblogs.com/LH2000/p/15045071.html
Copyright © 2011-2022 走看看