树上两点间距离 倍增法求LCA

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long L;
vector<int>vec[100010];
int dp[100010][30];
int d[100010],n,m;
void init()
{
    for(int i=0;i<=100000;i++)for(int j=0;j<=30;j++) dp[i][j]=0;
    for(int i=0;i<=100000;i++) d[i]=0,vec[i].clear();
}
void bfs(int x)
{
     d[x]=1;
     queue<int>q;q.push(x);
     int Lgn=(int)(log(n)/log(2));
     while(!q.empty()){
        int f=q.front();q.pop();
        int len=vec[f].size();
        for(int i=0;i<len;i++){
            int to=vec[f][i];
            if(!d[to]){
                q.push(to);
                d[to]=d[f]+1;
                dp[to][0]=f;
                for(int i=1;i<=Lgn;i++){
                    dp[to][i]=dp[dp[to][i-1]][i-1];
                }
            }
        }
     }
}

int Lca(int x,int y)
{
    if(d[x]<d[y]) swap(x,y);
    int lgn=(int)(log(n)/log(2));
    for(int i=lgn;i>=0;i--){
        int to=dp[x][i];
        if(d[to]>=d[y]){
            x=to;
        }
    }
    if(x==y) return x;
    for(int i=lgn;i>=0;i--){
        int tx=dp[x][i],ty=dp[y][i];
        if(tx!=ty){
            x=tx;y=ty;
        }
    }
    return dp[x][0];
}

int main()
{
    int t,cs=0;scanf("%d",&t);
    while(t--){
        init();
        int q;scanf("%d %d %d",&n,&m,&q);
        for(int i=1;i<n;i++){
            int u,v;scanf("%d %d",&u,&v);
            vec[u].pb(v);
            vec[v].pb(u);
        }
        bfs(m);
        printf("Case #%d:\n",++cs);
        while(q--){
            int x,y;scanf("%d %d",&x,&y);
            int lca=Lca(x,y);
            printf("%d\n",d[x]+d[y]-2*d[lca]);
        }
    }
}

发布了61 篇原创文章 · 获赞 7 · 访问量 3200

猜你喜欢

转载自blog.csdn.net/qq_43914084/article/details/102964543