zoukankan      html  css  js  c++  java
  • LCA 倍增||树链剖分

    方法1:倍增

    1498ms

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=5e5+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,q,root,a,b;
    struct edge{
        int v,ne;
    }e[N<<1];
    int cnt=0,h[N];
    inline void ins(int u,int v){
        cnt++;
        e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
    }
    int fa[N][21],deep[N],vis[N];
    void dfs(int u){
        vis[u]=1;
        for(int j=1;(1<<j)<=deep[u];j++)
            fa[u][j]=fa[fa[u][j-1]][j-1];
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(vis[v]) continue;
            deep[v]=deep[u]+1;
            fa[v][0]=u;
            dfs(v);
        }
    }
    int lca(int x,int y){
        if(deep[x]<deep[y]) swap(x,y);
        int bin=deep[x]-deep[y];
        for(int i=0;i<=16;i++)
            if((1<<i)&bin) x=fa[x][i];//,printf("x %d
    ",i);
        
        for(int i=16;i>=0;i--)
            if(fa[x][i]!=fa[y][i]){
                x=fa[x][i];
                y=fa[y][i];
            }
        if(x==y) return x;
        else return fa[x][0];
    }
    int main(int argc, const char * argv[]) {
        n=read();q=read();root=read();
        for(int i=1;i<=n-1;i++) a=read(),b=read(),ins(a,b);
        dfs(root);
        for(int i=1;i<=q;i++){
            a=read();b=read();
            printf("%d
    ",lca(a,b));
        }
        return 0;
    }

    方法2:树链剖分

    1314ms

    让链首深度大的走到重链的父节点直到在一条重链上,返回深度小的节点

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    using namespace std;
    typedef long long ll;
    const int N=5e5+5;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int n,q,root,a,b;
    struct edge{
        int v,ne;
    }e[N<<1];
    int cnt=0,h[N];
    inline void ins(int u,int v){
        cnt++;
        e[cnt].v=v;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].ne=h[v];h[v]=cnt;
    }
    int fa[N],deep[N],mx[N],size[N];
    void dfs(int u){
        size[u]++;
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(v==fa[u]) continue;
            fa[v]=u;deep[v]=deep[u]+1;
            dfs(v);
            size[u]+=size[v];
            if(size[v]>size[mx[u]]) mx[u]=v;
        }
    }
    int tid[N],top[N],tot;
    void dfs(int u,int anc){
        if(!u) return;
        tid[u]=++tot;top[u]=anc;
        dfs(mx[u],anc);
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(v!=fa[u]&&v!=mx[u]) dfs(v,v);
        }
    }
    int lca(int x,int y){
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]]) swap(x,y);
            x=fa[top[x]];
        }
        if(deep[x]>deep[y]) swap(x,y);
        return x;
    }
    int main(int argc, const char * argv[]) {
        n=read();q=read();root=read();
        for(int i=1;i<=n-1;i++) a=read(),b=read(),ins(a,b);
        dfs(root);
        dfs(root,root);
        for(int i=1;i<=q;i++){
            a=read();b=read();
            printf("%d
    ",lca(a,b));
        }
        return 0;
    }
  • 相关阅读:
    Qt的.pro文件
    AI_八数码
    安装 MINGW GCC 4.4.0
    VC中应用Excel
    八数码问题_启发搜索
    【收集】【收藏】【转帖】game development resouce
    QT小记之在VS2005中使用QT
    [转文]VS2008 安装 Boost 1.43.0
    搬家到博客园了
    转 暴雪总裁总结游戏十条经验
  • 原文地址:https://www.cnblogs.com/candy99/p/6172334.html
Copyright © 2011-2022 走看看