zoukankan      html  css  js  c++  java
  • 【倍增】洛谷P3379 倍增求LCA

    题目描述

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

    输入输出格式

    输入格式:

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

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

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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    5 5 4
    3 1
    2 4
    5 1
    1 4
    2 4
    3 2
    3 5
    1 2
    4 5
    输出样例#1: 复制
    4
    4
    1
    4
    4
    

    说明

    时空限制:1000ms,128M

    数据规模:

    对于30%的数据:N<=10,M<=10

    对于70%的数据:N<=10000,M<=10000

    对于100%的数据:N<=500000,M<=500000

    样例说明:

    该树结构如下:

    第一次询问:2、4的最近公共祖先,故为4。

    第二次询问:3、2的最近公共祖先,故为4。

    第三次询问:3、5的最近公共祖先,故为1。

    第四次询问:1、2的最近公共祖先,故为4。

    第五次询问:4、5的最近公共祖先,故为4。

    故输出依次为4、4、1、4、4。

    题解

    倍增求LCA的板子。。。

    反正就是处理好x向上1<<i 位的节点。。。

    然后从深度深的往上跳。。。

    代码

    //by 减维
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<queue>
    #include<cstdlib>
    #include<ctime>
    #include<cmath>
    #include<map>
    #include<bitset>
    #include<algorithm>
    #define ll long long
    using namespace std;
    
    struct edge{
        int to,ne;
    }e[1000005];
    
    int n,m,s,ecnt,dep[500005],head[500005],f[500005][21];
    
    void add(int x,int y)
    {
        e[++ecnt].to=y;
        e[ecnt].ne=head[x];
        head[x]=ecnt;
    }
    
    void dfs(int x,int fa)
    {
        dep[x]=dep[fa]+1;
        f[x][0]=fa;
        for(int i=1;(1<<i)<=dep[x];++i)
            f[x][i]=f[f[x][i-1]][i-1];
        for(int i=head[x];i;i=e[i].ne)
        {
            int dd=e[i].to;
            if(dd==fa)continue;
            dfs(dd,x);
        }
    }
    
    int lca(int x,int y)
    {
        if(dep[x]>dep[y])swap(x,y);
        for(int i=20;i>=0;--i)
            if(dep[x]<=dep[y]-(1<<i))y=f[y][i];
        if(x==y)return x;
        for(int i=20;i>=0;i--)
        {
            if(f[x][i]==f[y][i])continue;
            else x=f[x][i],y=f[y][i];
        }
        return f[x][0];
    }
    
    int main()
    {
        scanf("%d%d%d",&n,&m,&s);
        for(int x,y,i=1;i<n;++i)
        {
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        dfs(s,0);
        for(int x,y,i=1;i<=m;++i)
        {
            scanf("%d%d",&x,&y);
            printf("%d
    ",lca(x,y));
        }
    }
  • 相关阅读:
    hdu 2222 Keywords Search
    Meet and Greet
    hdu 4673
    hdu 4768
    hdu 4747 Mex
    uva 1513 Movie collection
    uva 12299 RMQ with Shifts
    uva 11732 strcmp() Anyone?
    uva 1401
    hdu 1251 统计难题
  • 原文地址:https://www.cnblogs.com/rir1715/p/7775175.html
Copyright © 2011-2022 走看看