{模板}LCA倍增

void Build(int x,int f)
{
    fa[x][0] = f,dep[x] = dep[f] + 1;
    int y = f,i = 1;
    while (y > 0)
    {
        fa[x][i] = fa[y][i - 1],
        y = fa[y][i - 1];
        i ++;
    }
    fm(tmp,x)
    if (e[tmp].to != f)
        Build(e[tmp].to,x);
}
int Lca(int x,int y)
{
    if (dep[x] > dep[y]) swap(x,y);
    int i = 0;
    for (int dis = dep[y] - dep[x];dis;dis >>= 1,i ++)
        if ((dis & 1) == 1) y = fa[y][i];
    if (x == y) return x;
    i = 0;
    while (fa[x][i] != fa[y][i]) i ++;
    i --;
    while (i >= 0)
    {
        while (i >= 0 && fa[x][i] == fa[y][i]) i --;
        if (i >= 0)
            x = fa[x][i],y = fa[y][i];
    }   
    return fa[x][0];
}
const
        maxn=40000;
        maxm=40000;
var
        root:longint;
    i,j,k,n,m,x,y,t:longint;
    deep:array[0..maxn] of longint;
    f:array[0..maxn,0..20] of longint;
    head:array[0..maxn*2,1..2] of longint;
        next:array[0..maxn*2,1..2] of longint;
procedure build(x,fa,d:longint);
var
    k,y,i:longint;
begin
    f[x,0]:=fa;
    deep[x]:=d;
    y:=fa;i:=1;
    while y>0 do
    begin
        f[x,i]:=f[y,i-1];
        y:=f[y,i-1];
        inc(i);
    end;
    k:=head[x,1];
    while k>0 do
    begin
        if next[k,1]=fa then
                begin
                        k:=next[k,2];
                        continue;
                end;
        build(next[k,1],x,d+1);
        k:=next[k,2];
    end;
end;
function lca(l,r:longint):longint;
var
    x,y,t,jump,i:longint;
    p:boolean;
begin
    x:=l;y:=r;
    if deep[x]>deep[y] then
        begin
                t:=x;
                x:=y;
                y:=t;
        end;
    jump:=deep[y]-deep[x];
        i:=0;
    while jump>0 do
    begin
        if jump and 1>0 then y:=f[y,i];
        inc(i);
        jump:=jump shr 1;
    end;
    if(x=y)then exit(x);
    i:=0;
    while(f[x,i]<>f[y,i])do inc(i); dec(i);
    while(i>=0)do
    begin
        while (i>=0) and (f[x,i]=f[y,i]) do dec(i);
        if i<0 then break;
        x:=f[x,i];y:=f[y,i];
    end;
    exit(f[x,0]);
end;
begin
    readln(n);
    for i:=1 to n do
    begin
        readln(x,y);
                if(y>0)then
                begin
                inc(t);
                if head[x,1]=0 then head[x,1]:=t;
                next[t,1]:=y;
                next[t,2]:=0;
                next[head[x,2],2]:=t;
                head[x,2]:=t;

                inc(t);
                if head[y,1]=0 then head[y,1]:=t;
                next[t,1]:=x;
                next[t,2]:=0;
                next[head[y,2],2]:=t;
                head[y,2]:=t;
                end
                else
                root:=x;
    end;

    build(root,0,0);
    readln(m);
    for i:=1 to m do
    begin
        readln(x,y);
                     if(lca(x,y)=x)then writeln('1')
                else if(lca(x,y)=y)then writeln('2')
                else writeln('0')
    end;
end.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值