模板lca的几种求法

Posted kkkek

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模板lca的几种求法相关的知识,希望对你有一定的参考价值。


1,倍增
vector<int>p[maxn];
int dep[maxn],f[maxn][20];//f[i][0]保存i的父亲 
inline void dfs(int u,int fa,int d)
{
    dep[u]=d;f[u][0]=fa;
    for(int i=0;i<p[u].size();i++)
    {
        int v=p[u][i];
        if(v==fa)continue;
        dfs(v,u,d+1);
    }
}
inline void init(int n)
{
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i<=n;i++)
            if(f[i][j-1])f[i][j]=f[f[i][j-1]][j-1];
    //i的第2^j祖先就是i的第2^(j-1)祖先的第2^(j-1)祖先
}
inline int LCA(int u,int v)
{
    int i=0,j;
    if(dep[u]<dep[v])swap(u,v);
    for(i=1;(1<<i)<=dep[u];i++);i--;//缩小j的范围 不缩小则 j从20左右开始递减 
    //使a,b两点的深度相同
    for(j=i;j>=0;j--)
        if(dep[u]-(1<<j)>=dep[v])u=f[u][j];
    if(u==v)return u;
    for(j=i;j>=0;j--)
    {
        if(f[u][j]!=-1&&f[u][j]!=f[v][j])
        {
            u=f[u][j];
            v=f[v][j];
        }
    }
    return f[u][0];
}
2,树链剖分
vector<int>p[maxn];
int siz[maxn],dep[maxn],fad[maxn],son[maxn],top[maxn],cnt;
inline void dfs1(int u,int fa,int d)
{
    dep[u]=d;fad[u]=fa;siz[u]=1;
    for(int i=0;i<p[u].size();i++)
    {
        int v=p[u][i];
        if(v==fa)continue;
        dfs1(v,u,d+1);
        siz[u]+=siz[v];
        if(siz[v]>siz[son[u]])son[u]=v;
    }
}
inline void dfs2(int u,int t)
{
    top[u]=t;
    if(!son[u])return;//当前节点不在重链上
    dfs2(son[u],t);
    for(int i=0;i<p[u].size();i++)
    {
        int v=p[u][i];
        if(v!=son[u]&&v!=fad[u])dfs2(v,v);//非重节点的top是自己
    }
}
inline int LCA(int u,int v)
{
    while(top[u]!=top[v])
    {
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        u=fad[top[u]];
    }
    if(dep[u]>dep[v])return v;
    return u;
}
3,st表 (最快
vector<int>p[maxn];
int depth[maxn<<1],id[maxn],rid[maxn<<1],cnt,st[maxn<<1][25];
inline void dfs(int u,int fa,int d)
{
    id[u]=++cnt;rid[cnt]=u;depth[cnt]=d;
    for(int i=0;i<p[u].size();i++)
    {
        if(p[u][i]==fa)continue;
        dfs(p[u][i],u,d+1);
        rid[++cnt]=u;depth[cnt]=d;
    }
}
int lg[maxn<<1];
inline void init()
{
    lg[0]=-1;
    for(int i=1;i<=cnt;i++)lg[i]=lg[i>>1]+1;
    for(int i=1;i<=cnt;i++)st[i][0]=i;
    for(int j=1;(1<<j)<=cnt;j++)
        for(int i=1;i+(1<<j)-1<=cnt;i++)
            st[i][j]=depth[st[i][j-1]]<depth[st[i+(1<<j-1)][j-1]]?
                    st[i][j-1]:
                    st[i+(1<<j-1)][j-1];
}
inline int LCA(int u,int v)
{
    if(id[u]>id[v])swap(u,v);
    int s=id[u],t=id[v],len=lg[t-s+1];
    return depth[st[s][len]]<depth[st[t-(1<<len)+1][len]]?rid[st[s][len]]:rid[st[t-(1<<len)+1][len]];
}



以上是关于模板lca的几种求法的主要内容,如果未能解决你的问题,请参考以下文章

LCS的几种求法

HDU 1576 -- A/B (总结乘法逆元的几种求法)

[线性代数] 3.矩阵乘法的几种求法

LCA 问题 + 模板

Laravel:如何在控制器的几种方法中重用代码片段

总结LCA的4种求法