• 洛谷 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。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 using namespace std;
     5 long long read()
     6 {
     7     long long x=0,f=1;
     8     char ch=getchar();
     9     while(ch>'9'||ch<'0')
    10     {
    11         if(ch=='-')
    12             f=-1;
    13         ch=getchar();
    14     }
    15     while(ch>='0'&&ch<='9')
    16     {
    17         x=x*10+ch-'0';
    18         ch=getchar();
    19     }
    20     return x*f;
    21 }
    22 const int maxn=500005;
    23 int n,m,s,k,a,b;
    24 int head[maxn],d[maxn],p[maxn][21];
    25 struct node
    26 {
    27     int v,next;
    28 } e[maxn*2];
    29 void add(int u,int v)
    30 {
    31     e[k].v=v;
    32     e[k].next=head[u];
    33     head[u]=k++;
    34 }
    35 void dfs(int u,int fa)
    36 {
    37     d[u]=d[fa]+1;
    38     p[u][0]=fa;
    39     for(int i=1; (1<<i)<=d[u]; i++)
    40         p[u][i]=p[p[u][i-1]][i-1];
    41     for(int i=head[u]; i!=-1; i=e[i].next)
    42     {
    43         int v=e[i].v;
    44         if(v!=fa)
    45             dfs(v,u);
    46     }
    47 }
    48 int lca(int a,int b)
    49 {
    50     if(d[a]>d[b])
    51         swap(a,b);
    52     for(int i=20; i>=0; i--)
    53         if(d[a]<=d[b]-(1<<i))
    54             b=p[b][i];
    55     if(a==b)
    56         return a;
    57     for(int i=20; i>=0; i--)
    58     {
    59         if(p[a][i]==p[b][i])
    60             continue;
    61         else
    62             a=p[a][i],b=p[b][i];
    63     }
    64     return p[a][0];
    65 }
    66 int main()
    67 {
    68     memset(head,-1,sizeof(head));
    69     n=read(),m=read(),s=read();
    70     for(int i=1; i<n; i++)
    71     {
    72         a=read(),b=read();
    73         add(a,b);
    74         add(b,a);
    75     }
    76     dfs(s,0);
    77     for(int i=1; i<=m; i++)
    78     {
    79         a=read(),b=read();
    80         printf("%d
    ",lca(a,b));
    81     }
    82     return 0;
    83 }
    倍增求LCA
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 const int maxn=2e6+10;
     6 #define ls k<<1
     7 #define rs k<<1|1
     8 long long read()
     9 {
    10     long long x=0,f=1;
    11     char ch=getchar();
    12     while(ch>'9'||ch<'0')
    13     {
    14         if(ch=='-')
    15             f=-1;
    16         ch=getchar();
    17     }
    18     while(ch>='0'&&ch<='9')
    19     {
    20         x=x*10+ch-'0';
    21         ch=getchar();
    22     }
    23     return x*f;
    24 }
    25 struct node
    26 {
    27     int v,nxt;
    28 } e[maxn];
    29 int head[maxn],fa[maxn],deep[maxn],tot[maxn],son[maxn],top[maxn];
    30 int num=1,cnt;
    31 void add(int x,int y)
    32 {
    33     e[num].v=y;
    34     e[num].nxt=head[x];
    35     head[x]=num++;
    36 }
    37 int dfs1(int now,int f,int dep)
    38 {
    39     deep[now]=dep;
    40     fa[now]=f;
    41     tot[now]=1;
    42     int maxson=-1;
    43     for(int i=head[now]; i; i=e[i].nxt)
    44     {
    45         if(e[i].v==f)
    46             continue;
    47         tot[now]+=dfs1(e[i].v,now,dep+1);
    48         if(tot[e[i].v]>maxson)
    49             maxson=tot[e[i].v],son[now]=e[i].v;
    50     }
    51     return tot[now];
    52 }
    53 void dfs2(int now,int topf)
    54 {
    55     top[now]=topf;
    56     if(!son[now])
    57         return ;
    58     dfs2(son[now],topf);
    59     for(int i=head[now]; i; i=e[i].nxt)
    60         if(e[i].v!=son[now]&&e[i].v!=fa[now])
    61             dfs2(e[i].v,e[i].v);
    62 }
    63 int LCA(int x,int y)
    64 {
    65     while(top[x]!=top[y])
    66     {
    67         if(deep[top[x]]<deep[top[y]])
    68             swap(x,y);
    69         x=fa[top[x]];
    70     }
    71     if(deep[x]>deep[y])
    72         swap(x,y);
    73     return x;
    74 }
    75 int main()
    76 {
    77     memset(head,0,sizeof(head));
    78     int n=read(),m=read(),root=read();
    79     for(int i=1; i<=n-1; i++)
    80     {
    81         int x=read(),y=read();
    82         add(x,y),add(y,x);
    83     }
    84     dfs1(root,0,1);
    85     dfs2(root,root);
    86     while(m--)
    87     {
    88         int x=read(),y=read();
    89         printf("%d
    ",LCA(x,y));
    90     }
    91     return 0;
    92 }
    树链剖分求LCA
  • 相关阅读:
    磁盘相关命令
    shell $用法
    setuid setgid stick bit 特殊权限 粘滞位
    运维面试题2
    mysql 外键约束
    创建MySQL 用户
    shell 脚本定时创建月份表
    apache 配置多个虚拟主机,不同的端口
    sublime3中文乱码解决包ConvertToUTF8.zip
    yii2安装
  • 原文地址:https://www.cnblogs.com/liweilin/p/10198885.html
Copyright © 2020-2023  润新知