首页 > 代码库 > LCA

LCA

 

 

 

 

 

A LCA-2 摸底考

背景&&描述

    给出一棵根节点为1的树,每次询问两点之间的最近公共祖先。

 

输入格式

    第一行一个整数n表示树的节点个数

    第二行n-1个数,第i个数表示点(i+1)的父亲是哪个点。保证第i个数<=i。

    第三行一个整数m表示询问个数。

    接下来m行,每行有俩整数,表示询问的俩点。

输出格式

    共m行,对于每次询问输出最近公共祖先的编号。

样例输入

A LCA-2 摸底考

背景&&描述

    给出一棵根节点为1的树,每次询问两点之间的最近公共祖先。

 

输入格式

    第一行一个整数n表示树的节点个数

    第二行n-1个数,第i个数表示点(i+1)的父亲是哪个点。保证第i个数<=i。

    第三行一个整数m表示询问个数。

    接下来m行,每行有俩整数,表示询问的俩点。

输出格式

    共m行,对于每次询问输出最近公共祖先的编号。

样例输入

6
1 2 1 2 4
3
3 5
6 4
2 6

 

样例输出

2
4
1

数据范围与约定

  • 对于100%的数据:技术分享
6
1 2 1 2 4
3
3 5
6 4
2 6

 

样例输出

2
4
1

数据范围与约定

  • 对于100%的数据:技术分享
技术分享
#include<cstdio>
#include<algorithm>
#include<cstring>
const int N=200050;
struct node
{
    int to,next;
}e[N];
int first[N],dep[N],visit[N];
int fa[N][30];
int cnt=0;
void insert(int u,int v)
{
    e[++cnt].to=v;e[cnt].next=first[u];first[u]=cnt;
    e[++cnt].to=u;e[cnt].next=first[v];first[v]=cnt;
}
void dfs(int x)
{
    visit[x]=1;
    for(int i=1;(1<<i)<=dep[x];i++)
        fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int k=first[x];k;k=e[k].next)    
    if(!visit[e[k].to])
    {
        fa[e[k].to][0]=x;
        dep[e[k].to]=dep[x]+1;
        dfs(e[k].to);
    }
}
int getlca(int x,int y)
{
    if(dep[x]<dep[y])    std::swap(x,y);
    int t=dep[x]-dep[y];
    for(int i=0;(1<<i)<=t;i++)
    if((1<<i)&t)    x=fa[x][i];

    for(int i=25;i>=0;i--)
    if((1<<i)<=dep[x]&&fa[x][i]!=fa[y][i])
    x=fa[x][i],y=fa[y][i];
    if(x==y)    return x;
    return fa[x][0];
}
int main()
{
    int n;    
    scanf("%d",&n);
    int k;
    for(int i=2;i<=n;i++)        scanf("%d",&k),insert(i,k);
    dfs(1);
    int m;
    scanf("%d",&m);
    int p,q;
    for(int i=1;i<=m;i++)    scanf("%d %d",&p,&q),printf("%d\n",getlca(p,q));
    return 0;    
}
View Code

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

LCA模版 

谢谢brain551的教导;

可以去看他的博客,贼好.

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

 这个一道基本上一模一样的题:

给出一棵以1为根的有n个节点的树。

m个询问,每次询问ab的最近公共祖先。

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

要LCA理解的可以去看看:

http://www.cnblogs.com/yyf0309/p/5972701.html

LCA