zoukankan      html  css  js  c++  java
  • 洛谷 P3379 【模板】最近公共祖先(LCA) 如题

    P3379 【模板】最近公共祖先(LCA)

    • 时空限制1s / 512MB

    题目描述

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

    输入输出格式

    输入格式:

    第一行包含三个正整数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。

    ----------------------------------------------------------------------------------------------------------------

    注意题目中的边是无向的,所以要建双向,所以边数应为m*2,需要开两倍数组(我没注意只开了一倍就蠢蠢地submit结果。。。)

    这里的倍增+LCA

    把表示幂的一维放到前面

    就是把小的一维放到前面

    会对内存友好

    听说就会快很多 

    存板子:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<iostream>
     4 #define maxn 500010
     5 using namespace std;
     6 struct node{
     7     int to,next;
     8 };
     9 node e[maxn<<1];
    10 int read();
    11 int n,m,s,pre[maxn],cnt,len[maxn],p[23][maxn];
    12 bool po[maxn];
    13 int lca(int,int);
    14 void dfs(int);
    15 void ycl();
    16 void build(int,int);
    17 int main(){
    18     memset(po,0,sizeof(po));
    19     n=read();m=read();s=read();
    20     cnt=0;
    21     for(int i=1;i<n;i++){
    22         int x=read(),y=read();
    23         build(x,y);
    24     }
    25     len[s]=1;po[s]=1;
    26     dfs(s);
    27     ycl();
    28     for(int i=1;i<=m;i++){
    29         int x=read(),y=read();
    30         printf("%d
    ",lca(x,y));
    31     }
    32     return 0;
    33 }
    34 int lca(int x,int y){
    35     if(len[x]>len[y]) swap(x,y);
    36     int k=len[y]-len[x];
    37     for(int j=0;(1<<j)<=k;j++)
    38     if((1<<j)&k) y=p[j][y];
    39     if(x==y) return x;
    40     for(int j=21;j>=0;j--)
    41        if(p[j][x]!=p[j][y]){
    42            x=p[j][x];
    43            y=p[j][y];
    44        }
    45     return p[0][y];
    46 }
    47 void dfs(int x){
    48     for(int i=pre[x];i;i=e[i].next){
    49         int to=e[i].to;
    50         if(!po[to]){
    51             po[to]=1;
    52             len[to]=len[x]+1;
    53             p[0][to]=x;
    54             dfs(to);
    55         }
    56     }
    57 }
    58 void ycl(){
    59     for(int j=1;(1<<j)<=n;j++)
    60        for(int i=1;i<=n;i++)
    61        p[j][i]=p[j-1][p[j-1][i]];
    62 }
    63 void build(int x,int y){
    64     e[++cnt].to=y;e[cnt].next=pre[x];pre[x]=cnt;
    65     e[++cnt].to=x;e[cnt].next=pre[y];pre[y]=cnt;
    66 }
    67 int read(){
    68     int ans=0,f=1;char c=getchar();
    69     while('0'>c||c>'9'){if(c=='-')f=-1;c=getchar();}
    70     while('0'<=c&&c<='9')ans=ans*10+c-48,c=getchar();return ans*f;
    71 }
    倍增+LCA
  • 相关阅读:
    Java hutool/java 常用方法
    版本控制工具 TortoiseGit 基本配置
    SpringBlade 码云上我自己的fork的仓库简单使用
    版本控制工具 Git SourceTree SSH 连接码云
    版本控制工具 Git SourceTree 报错 fatal: could not read Username for 'https://gitee.com': No such file or directory
    在充电桩联网部署方案中4G DTU的优势是什么
    4G DTU模块和串口设备连接的方式
    4g物联网模块的原理
    4G DTU采用的4G通信模块介绍
    4G DTU数据传输终端的功能介绍
  • 原文地址:https://www.cnblogs.com/lpl-bys/p/7811808.html
Copyright © 2011-2022 走看看