zoukankan      html  css  js  c++  java
  • 【树】LCA的几种求法

    LCA的几种求法

    1,st表 (最快~

    int depth[maxn<<1],id[maxn],rid[maxn<<1],cnt,st[maxn<<1][25];
    void dfs(int u,int fa,int d)
    {
        id[u]=++cnt;rid[cnt]=u;depth[cnt]=d;
        for(int i=head[u];i;i=nxt[i]){
            if(to[i]==fa)continue;
            dfs(to[i],u,d+1);
            rid[++cnt]=u;depth[cnt]=d;
        }
    }
    int lg[maxn<<1];
    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];
    }
    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]];
    }
    

    2,倍增

    int dep[maxn],f[maxn][20];
    void dfs(int u,int fa,int d)
    {
        dep[u]=d;f[u][0]=fa;
        for(int i=head[u];i;i=nxt[i])
            if(to[i]!=fa)dfs(to[i],u,d+1);
    }
    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];
    }
    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--;
        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];
    }
    

    下面这个代码简单点:

    int din[maxn],dout[maxn],tnt,f[maxn][25];
    void dfs(int u,int fa)
    {
    	din[u]=++tnt;f[u][0]=fa;
    	for(int i=1;i<=20;i++)f[u][i]=f[f[u][i-1]][i-1];
    	for(int i=head[u];i;i=nxt[i])
    		if(to[i]!=fa)dfs(to[i],u);
    	dout[u]=++tnt;	
    }
    inline bool upper(int u,int v){
    	return din[u]<=din[v]&&dout[u]>=dout[v];
    }
    int LCA(int u,int v)
    {
    	if(upper(u,v))return u;
    	for(int i=20;i>=0;i--)
    	if(!upper(f[u][i],v))u=f[u][i];
    	return f[u][0];
    }
    

    3,树剖

    int siz[maxn],dep[maxn],fad[maxn],son[maxn],top[maxn],cnt;
    void dfs1(int u,int fa,int d)
    {
        dep[u]=d;fad[u]=fa;siz[u]=1;son[u]=0;
        for(int i=head[u];i;i=nxt[i])
        {
            if(to[i]==fa)continue;
            dfs1(to[i],u,d+1);
            siz[u]+=siz[to[i]];
            if(siz[to[i]]>siz[son[u]])son[u]=to[i];
        }
    }
    void dfs2(int u,int t)
    {
        top[u]=t;
        if(!son[u])return;
        dfs2(son[u],t);
        for(int i=head[u];i;i=nxt[i])
            if(to[i]!=son[u]&&to[i]!=fad[u])dfs2(to[i],to[i]);
    }
    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;
    }
    

    4,LCT (可动态求LCA

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=5e5+5;
    
    //LCT
    struct LCT{
        int ch[maxn][2],f[maxn],tag[maxn],val[maxn],xs[maxn];
        inline int getch(int x){return ch[f[x]][1]==x;}
        inline int isroot(int x){return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;}
        inline void pushdown(int p){
            if(tag[p]){
                if(ch[p][0])swap(ch[ch[p][0]][0],ch[ch[p][0]][1]),tag[ch[p][0]]^=1;
                if(ch[p][1])swap(ch[ch[p][1]][0],ch[ch[p][1]][1]),tag[ch[p][1]]^=1;
                tag[p]=0;
            }
        }
        inline void pushup(int x){xs[x]=val[x]^xs[ch[x][0]]^xs[ch[x][1]];}
        void update(int p){
            if (!isroot(p))update(f[p]);
            pushdown(p);
        }
        inline void rotate(int x){
            int y=f[x],z=f[y],k=getch(x);
            if (!isroot(y))ch[z][ch[z][1]==y]=x;
            ch[y][k]=ch[x][!k],f[ch[x][!k]]=y;
            ch[x][!k]=y,f[y]=x,f[x]=z;
            pushup(x),pushup(y);
        }
        inline void splay(int x){
            update(x);
            for(int fa;fa=f[x],!isroot(x);rotate(x)){
                if(!isroot(fa))rotate(getch(fa)==getch(x)?fa:x);
            }
            pushup(x);
        }
        inline int access(int x){
            int p;
            for(p=0;x;p=x,x=f[x]){
                splay(x);ch[x][1]=p;pushup(x);
            }
            return p;
        }
        inline void makeroot(int p){
            access(p);splay(p);
            swap(ch[p][0],ch[p][1]);
            tag[p]^=1;
        }
        inline void link(int x,int p){
            if(find(x)==find(p))return;
            makeroot(x);
            splay(x);
            f[x]=p;
        }
        inline void split(int x,int y){
            makeroot(x);access(y);splay(y);
        }
        inline void cut(int x,int p){
            split(x,p);
            if(ch[p][0]==x&&!ch[x][1])ch[p][0]=f[x]=0;
        }
        inline int find(int p){
            access(p);splay(p);
            while(ch[p][0])p=ch[p][0];
            splay(p);
            return p;
        }
        inline int lca(int x,int y){access(x);return access(y);}
    }st;
    int main()
    {
        int n,m,s,u,v;
        scanf("%d%d%d",&n,&m,&s);
        for(int i=1;i<n;i++){
            scanf("%d%d",&u,&v);
            st.link(u,v);
        }
        st.makeroot(s);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            printf("%d
    ",st.lca(u,v));
        }
    }
    
  • 相关阅读:
    ios framework 使用图片资源
    XCode 6.4 Alcatraz 安装的插件不可用
    prefix pch 中引用cocoapods 中的头文件失败
    Xcode 6添加模板无效
    获取当前日期是星期几
    玩转iOS开发:《使用系统自带的UIActivityViewController和UIActivity进行内容分享》
    玩转iOS开发:《iOS设计模式 — 代理模式》
    玩转iOS开发:《iOS设计模式 — 单例模式》
    iOS开发技巧-Swift版本: 3.Storyboard传参小技巧
    UIKit应用
  • 原文地址:https://www.cnblogs.com/kkkek/p/12297320.html
Copyright © 2011-2022 走看看