zoukankan      html  css  js  c++  java
  • luogu_P3379 【模板】最近公共祖先(LCA)

    https://www.luogu.org/problem/P3379

    题目描述

    如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。

    输入格式

    第一行包含三个正整数N、M、S,分别表示树的结点个数、询问的个数和树根结点的序号。

    接下来N-1行每行包含两个正整数x、y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树)。

    接下来M行每行包含两个正整数a、b,表示询问a结点和b结点的最近公共祖先。

    输出格式

    输出包含M行,每行包含一个正整数,依次为每一个询问的结果。


    倍增法log(2)级

    fa[x][i]表示从x向上爬(1<<i)次到达的祖先,即f[x][0]为向上爬(1<<0)=1次为x的父节点

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    
    #define ri register int
    #define u int
    #define NN 500005
    #define MM 500005
    
    namespace fast {
    
        inline u in() {
            u x(0),f(1);
            char s=getchar();
            while(s<'0'||s>'9') {
                if(s=='-') {
                    f=-1;
                }
                s=getchar();
            }
            while(s>='0'&&s<='9') {
                x=(x<<1)+(x<<3)+s-'0';
                s=getchar();
            }
            return x*f;
        }
    
    }
    
    using fast::in;
    
    namespace all {
    
        u N,M,S,mxd,d[NN],fa[NN][20];
    
        u cnt,h[NN];
        struct node {
            u to,next;
        } a[MM<<1];
        inline void add(const u &x,const u &y) {
            a[++cnt].next=h[x],a[cnt].to=y,h[x]=cnt;
        }
    
        void dfs(const u &x,const u &prt,const u &deep) {
            d[x]=deep,fa[x][0]=prt,mxd=std::max(mxd,deep);
            for(ri i(h[x]); i; i=a[i].next) {
                u _y(a[i].to);
                if(_y^prt) {
                    dfs(_y,x,deep+1);
                }
            }
        }
    
        u climb(u x,u y) {
            if(d[x]>d[y]) {
                std::swap(x,y);
            }
            u _k((u)(log(d[y])/log(2)));
            for(ri i(_k); i>=0; --i) {
                if(d[y]-(1<<i)>=d[x]) {
                    y=fa[y][i];
                }
            }
            if(x==y) return x;
            for(ri i(_k); i>=0; --i) {
                if(fa[x][i]^fa[y][i]) {
                    x=fa[x][i],y=fa[y][i];
                }
            }
            return fa[x][0];
        }
    
        inline void solve() {
            N=in(),M=in(),S=in();
            for(ri i(1); i<N; ++i) {
                u _a(in()),_b(in());
                add(_a,_b),add(_b,_a);
            }
            dfs(S,0,1);
            for(ri j(1); mxd-(1<<j)>=1; ++j) {
                for(ri i(1); i<=N; ++i) {
                    fa[i][j]=fa[fa[i][j-1]][j-1];
                }
            }
            for(ri i(1); i<=M; ++i) {
                u _a(in()),_b(in());
                printf("%d
    ",climb(_a,_b));
            }
        }
    
    }
    
    int main() {
    
        //freopen("x.txt","r",stdin);
        all::solve();
    
    }
  • 相关阅读:
    思念
    空白
    curl json string with variable All In One
    virtual scroll list All In One
    corejs & RegExp error All In One
    socket.io All In One
    vue camelCase vs PascalCase vs kebabcase All In One
    element ui 表单校验,非必填字段校验 All In One
    github 定时任务 UTC 时间不准确 bug All In One
    input range & color picker All In One
  • 原文地址:https://www.cnblogs.com/ling-zhi/p/11720110.html
Copyright © 2011-2022 走看看