题目描述

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

输入输出格式

输入格式:

 

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

样例说明:

该树结构如下:

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

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

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

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

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

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

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

显然的这道题就是模板的LCA

code:

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
const int N=500005;
int lg[N];
int ne=0,n,m,s,head[N],fa[N][22],deep[N];

int read()
{
    int ans=0,f=1;
    char c;
    c=getchar();
    while(c<'0'||c>'9')
    {
        if(c=='-')
        f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9')
    {
        ans=ans*10+c-'0';
        c=getchar();
    }
    return ans*f;
}

struct node
{
    int v;
    int next;
    int w;
}e[N*2];

void addedge(int u,int v)
{
    ne++;
    e[ne].v=v;
    e[ne].next=head[u];
    head[u]=ne;
    return ;
}

void dfs(int f,int fath)//fΪµ±Ç°£¬fathΪ¸¸Ç×½Úµã 
{
    deep[f]=deep[fath]+1;
    fa[f][0]=fath;
    for(int i=1;(1<<i)<=deep[f];i++)
        fa[f][i]=fa[fa[f][i-1]][i-1];
    for(int i=head[f];i;i=e[i].next)
        if(e[i].v!=fath)
            dfs(e[i].v,f);
}

int lca(int u,int v)//控制深度,使得u一定比v深

{
    if(deep[u]<deep[v])
    {
        swap(u,v);
    }
    while(deep[u]>deep[v])//使得u,v控制在同一个的深度
    u=fa[u][lg[deep[u]-deep[v]]-1]; 
    if(u==v)
    return v;
    for(int i=lg[deep[u]]-1;i>=0;i--)
    {
        if(fa[u][i]!=fa[v][i])
        {
            u=fa[u][i];
            v=fa[v][i];
        }
    }
    return fa[u][0];
}

int main()
{
    n=read();m=read();s=read();
    int x,y;
    for(int i=1;i<=n;i++)
    lg[i]=lg[i-1]+(1<<lg[i-1]==i); 
    for(int i=1;i<=n-1;i++)
    {
    	x=read();
    	y=read();
    	addedge(x,y);
    	addedge(y,x);
    }
    dfs(s,0);//建树
    for(int i=1;i<=m;i++)
    {
        x=read();
        y=read();
        printf("%d\n",lca(x,y));
    }
    return 0;
}

 

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-09-15
  • 2021-07-29
  • 2022-12-23
猜你喜欢
  • 2021-11-28
  • 2021-12-04
  • 2021-09-14
  • 2021-12-27
相关资源
相似解决方案