*树上倍增(LCA)

今天是2017/7/10,DCDCBigBig的第二十三篇博文

树上倍增(LCA)

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
struct edge{
    int v,next;
}a[100001];
int n,q,u,v,rt,tot=0,head[100001],fa[100001][31],dep[100001];
bool vis[100001];
void add(int u,int v){
    a[++tot].v=v;
    a[tot].next=head[u];
    head[u]=tot;
}
void cal_dep(int u){
    vis[u]=true;
    for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
        int v=a[tmp].v;
        if(!vis[v]){
            dep[v]=dep[u]+1;
            cal_dep(v);
        }
    }
}
void cal(){
    for(int j=1;j<=30;j++){
        for(int i=1;i<=n;i++){
            fa[i][j]=fa[fa[i][j-1]][j-1];
        }
    }
}
int lca(int x,int y){
    if(dep[x]<dep[y]){
        swap(x,y);
    }
    int s=dep[x]-dep[y];
    for(int i=0;i<30;i++){
        if((1<<i)&s)x=fa[x][i];
    } 
    if(x==y)return x;
    for(int i=29;i>=0;i--){
        if(fa[x][i]!=fa[y][i]){
            x=fa[x][i];
            y=fa[y][i];
        }
    }
    return fa[x][0];
}
int main(){
    memset(head,-1,sizeof(head));
    memset(fa,0,sizeof(fa));
    memset(dep,0,sizeof(dep));
    memset(vis,0,sizeof(vis));
    scanf("%d%d",&n,&q);
    for(int i=1;i<n;i++){
        scanf("%d%d",&u,&v);
        add(u,v);  
        fa[v][0]=u;
    }
    dep[1]=1;
    cal_dep(1);
    cal();
    for(int i=1;i<=q;i++){
        scanf("%d%d",&u,&v);
        printf("%d\n",lca(u,v));
    }
    return 0;
}
/*
16 4
1 2
1 3
2 4
2 5
2 6
3 7
4 8
4 9
5 10
7 11
7 12
10 13
10 14
10 15
12 16
4 7
9 16
11 16
15 8
------
1
1
7
2
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值