• [最近公共祖先]最近公共祖先(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的学习笔记

     1 #include <iostream>
     2 #include <bits/stdc++.h>
     3 using namespace std;
     4 const int N = 5e5+50;
     5 int n,m,s;
     6 int head[N],dep[N],p[N][22];
     7 int lg[N];
     8 struct node{
     9     int to,net;
    10 };
    11 node edge[N*2];
    12 int cnt=0;
    13 void add(int u,int v){
    14     edge[++cnt].to=v;
    15     edge[cnt].net=head[u];
    16     head[u]=cnt;
    17 }
    18 void init(){
    19     for(register int i=1;i<=n;i++){
    20         lg[i]=lg[i-1]+(1<<lg[i-1]==i);
    21     }
    22 }
    23 void dfs(int u,int fa){
    24     dep[u]=dep[fa]+1;
    25     p[u][0]=fa;
    26     for(register int i=1;(1<<i)<=dep[u];i++){
    27         p[u][i]=p[p[u][i-1]][i-1];
    28     }
    29     for(register int i=head[u];i;i=edge[i].net){
    30         if(edge[i].to==fa)
    31             continue;
    32         dfs(edge[i].to,u);
    33     }
    34 }
    35 int lca(int x,int y){
    36     if(dep[x]<dep[y]){
    37         swap(x,y);
    38     }
    39     while(dep[x]>dep[y]){
    40         x=p[x][lg[dep[x]-dep[y]]-1];
    41     }
    42     if(x==y)
    43         return x;
    44     for(register int k=lg[dep[x]];k>=0;k--){
    45         if(p[x][k]!=p[y][k]){
    46             x=p[x][k];
    47             y=p[y][k];
    48         }
    49     }
    50     return p[x][0];
    51 }
    52 int main()
    53 {
    54     memset(head,-1,sizeof(head));
    55     scanf("%d%d%d",&n,&m,&s);
    56     for(register int i=1;i<n;i++){
    57         int x,y;
    58         scanf("%d %d",&x,&y);
    59         add(x,y);
    60         add(y,x);
    61     }
    62     init();
    63     dfs(s,0);
    64     for(register int i=1;i<=m;i++){
    65         int a,b;
    66         scanf("%d %d",&a,&b);
    67         int ans=lca(a,b);
    68         printf("%d
    ",ans);
    69     }
    70     //cout << "Hello world!" << endl;
    71     return 0;
    72 }
    View Code
  • 相关阅读:
    调戏木马病毒的正确姿势——下
    调戏木马病毒的正确姿势——上
    可恢复的安全rm
    关于System.Convert那些事
    ORA-00600: internal error code, arguments: [kkqtSetOp.1]
    PL/SQL个人学习笔记
    苹果iOS手机后门的”诊断功能论“不攻自破
    畅谈HTML开发
    Triangle
    Java中的equals()和hashCode()
  • 原文地址:https://www.cnblogs.com/SoulSecret/p/9698501.html
Copyright © 2020-2023  润新知