点的距离(LCA)

试题描述
给定一棵有n个结点的树,Q 个询问,每次询问点x到点y两点之间的距离。
输入
第一行一个n,表示这棵树有n个结点。接下来n−1行,每行两个整数x,y表示x,y之间有一条连边。然后一个整数Q,表示有Q个询问,接下来Q行每行两个整数x,y表示询问x到y的距离。
输出
输出 Q 行,每行表示每个询问的答案。
输入示例
6
1 2
1 3
2 4
2 5
3 6
2
2 6
5 6
输出示例
3
4
其他说明
数据范围:1<=n<=10e5, 1<=x,y<=n

只能说是个LCA的板子

要是不知道LCA的看我博客吧:https://www.cnblogs.com/WWHHTT/p/9804966.html

下面给出代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
inline int rd(){
    int x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    return x*f;
}
inline void write(int x){
    if(x<0) putchar('-'),x=-x;
    if(x>9) write(x/10);
    putchar(x%10+'0');
    return ;
}
int n,m;
int f[100006][18];
int head[100006],to[100006],nxt[100006];
int d[100006];
int total=0;
void add(int x,int y){
    total++;
    to[total]=y;
    nxt[total]=head[x];
    head[x]=total;
    return ;
}
void dfs(int x,int fa){
    f[x][0]=fa;
    for(int e=head[x];e;e=nxt[e]){
        d[to[e]]=d[x]+1;
        dfs(to[e],x);
    }
    return ;
}
void pre(){for(int j=1;j<=17;j++) for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1];}
int LCA(int x,int y){
    if(d[x]<d[y]) swap(x,y);
    for(int i=17;i>=0;i--) if(d[f[x][i]]>=d[y]) x=f[x][i];
    if(x==y) return x;
    for(int i=17;i>=0;i--) if(f[x][i]!=f[y][i]){
        x=f[x][i],y=f[y][i];
    }
    return f[x][0];
}
int main(){
    n=rd();
    for(int i=1;i<n;i++){
        int x=rd(),y=rd();
        add(x,y);
    }
    d[1]=1;dfs(1,0);pre();
    m=rd();
    for(int i=1;i<=m;i++){
        int x=rd(),y=rd();
        write(d[x]+d[y]-(d[LCA(x,y)]*2)),puts("");
    }
    return 0;
}

 

posted @ 2018-10-17 16:39  Bruce--Wang  阅读(480)  评论(0编辑  收藏  举报