试题描述
|
给定一棵有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; }