首页 > 其他 > 详细

BSOJ1620 -- 【LCA练习】最近公共祖先(版本2)3587

时间:2019-05-26 19:09:48      阅读:115      评论:0      收藏:0      [点我收藏+]

类似于luogu P3379 【模板】最近公共祖先(LCA)

 

Description

  给你一棵有根树,要求你计算出指定两个结点的最近公共祖先。

Input

  输入文件的第一行为结点个数n(2<=N<=200,000),结点编号为1到n
  接下来n-1行,每行两个整数,第一个数字是第二个数字的父亲结点
  接下来的一行为两个整数a和b,要求计算出结点a和b的最近公共祖先。

Output

  输出文件仅一行为最近公共祖先的编号。

Sample Input

5 2 3 3 4 3 1 1 5 3 5

Sample Output

3

爬树法(树上倍增):
动态做法,边输入边找树根(套路)
 
预处理出p[i][k]代表i的第k代祖先,d[i]代表节点i的深度
之后用LCA爬树法重点处理:
  1)使d[L]>d[R],否则交换,方便后面处理
  2)计算出最多跳跃深度k=log2(d[L])
  3)L跳到与R深度相同
  4)L,R同时跳到LCA的子节点处
  5)计算出LCA
 
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define why 200005
struct starr
{
    int next,to;
}a[why<<1];
int n,root,p[why][18],d[why],prt[why],h[why],cnt;
void add(int x,int y)
{
    cnt++;
    a[cnt].to=y;
    a[cnt].next=h[x];
    h[x]=cnt;
}
void DFS(int x,int num)
{
    d[x]=num;
    for(int u=h[x];u;u=a[u].next)
    {
        int y=a[u].to;
        DFS(y,num+1);
    }
}
void ST()
{
    for(int i=1;i<=n;i++)p[i][0]=prt[i];
    for(int j=1;(1<<j)<=n;j++)
    {
        for(int i=1;i<=n;i++)
        {
            if(p[i][j-1]==-1)continue;
            p[i][j]=p[p[i][j-1]][j-1];
        }
    }
}
int LCA(int L,int R)
{
    int k;
    if(L==R)return L;
    if(d[L]<d[R])swap(L,R);
    k=int(log(d[L])/log(2));//k=log2(d[L]);用log()代替log2,c++自带log2函数效率不高
    for(int i=k;i>=0;i--)
    {
        if(d[L]-(1<<i)>d[R])L=p[L][i];
        else if(d[L]-(1<<i)==d[R])
        {
            L=p[L][i];
            break;
        }
    }
    if(L==R)return L;
    for(int i=k;i>=0;i--)
    {
        if(p[L][i]!=-1&&p[L][i]!=p[R][i])
        {
            L=p[L][i];
            R=p[R][i];
        }
    }
    return p[L][0];
}
int main()
{
    int _1,_2;
    scanf("%d",&n);
    memset(p,-1,sizeof(p));
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&_1,&_2);
        prt[_2]=_1;
        add(_1,_2);
        if(i==1||_2==root)root=_1;
    }
    DFS(root,1);
    ST();
    scanf("%d%d",&_1,&_2);
    printf("%d",LCA(_1,_2));
    return 0;
}

Tarjan离线求LCA(待填)

RMQ/LCT求LCA 有兴趣再说

BSOJ1620 -- 【LCA练习】最近公共祖先(版本2)3587

原文:https://www.cnblogs.com/NOI-AKer/p/Easy_LCA.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!