题目
题目描述
Vincent
和他的大学GF
不在同一个院系中,但他们每天都要约在校园中的同一个地方见面
THU
的地图可以抽象为一个
n
n
n个结点的一棵树,即有
n
n
n个地点,
n
−
1
n-1
n−1条无向边,每条边的长度为
1
1
1,任意两个地点之间是连通的树还能不连通!?
由于每天的课程不同,他们每天所在的位置也不同,第
i
i
i天,Vincent
在地点
x
i
x_i
xi,他的GF
在地点
y
i
y_i
yi
由于不能让某一方走的路程过多,所以他们约会的地点有个要求,必须与两人的位置之间的距离相等,距离指在树上的最短路径
请你帮Vincent
算算每天他们有多少种可选的约会地点
输入格式
第一行一个整数
n
n
n
接下来
n
−
1
n-1
n−1行,每行两个整数
u
u
u和
v
v
v,表示树上有一条
u
u
u和
v
v
v之间的边
接下来一行一个整数
m
m
m,表示他们有
m
m
m天要约会见面
接下来
m
m
m行,每行两个整数
x
i
,
y
i
x_i,y_i
xi,yi,表示第
i
i
i天,他们各自的位置
输出格式
对于每一天,输出一行一个整数,表示第 i i i天可行的约会地点有多少个
样例
样例输入
4
1 2
1 3
2 4
1
2 3
样例输出
1
数据范围与提示
样例解释
约会地点 1 1 1是可行的
数据范围及约定
对于
25
%
25 \%
25%的数据,
n
,
m
⩽
100
n,m \leqslant 100
n,m⩽100
对于
50
%
50 \%
50%的数据,
n
,
m
⩽
1
0
3
n,m \leqslant 10^3
n,m⩽103
另外存在
20
%
20 \%
20%的数据,树是一条链
另外存在
15
%
15 \%
15%的数据,树是随机生成的
对于
100
%
100 \%
100%的数据,
n
,
m
⩽
1
0
5
n,m \leqslant 10^5
n,m⩽105
题解
首先,以编号为
1
1
1的点为根
对于一组询问
x
,
y
x,y
x,y,如果
x
x
x的深度小于
y
y
y,那就交换他们的顺序
接着,求出它们的LCA,就可以求出链的长度
如果链的长度是偶数,那就没有中点,答案是
0
0
0
如果链的长度是奇数,就求出链的中点
如果中点是它们的LCA,那么深度比LCA小的节点和不包含
x
x
x和
y
y
y的LCA的子树是可行的约会地点
若中点不是LCA,那么深度小于中点的点都不是可行的约会地点,深度大于中点的节点用类似于上面的求法求出来就可以了
附上代码:
#include<iostream>
using namespace std;
int n,m,tot,head[100010],nxt[200010],to[200010],dep[100010],Fa[100010][25],size[100010];
void add(int a,int b)
{
nxt[++tot]=head[a],head[a]=tot,to[tot]=b;
}
void dfs(int x,int fa)
{
dep[x]=dep[fa]+1,size[x]=1,Fa[x][0]=fa;
for(int i=1;i<=20;i++) Fa[x][i]=Fa[Fa[x][i-1]][i-1];
for(int i=head[x];i;i=nxt[i]) if(to[i]^fa) dfs(to[i],x),size[x]+=size[to[i]];
}
int lca(int x,int y)
{
for(int i=20;~i;i--) if(dep[Fa[x][i]]>=dep[y]) x=Fa[x][i];
for(int i=20;~i;i--) if(Fa[x][i]^Fa[y][i]) x=Fa[x][i],y=Fa[y][i];
if(x^y) return Fa[x][0];
else return y;
}
int find(int x,int y)
{
for(int i=20;~i;i--) if(y>>i&1) x=Fa[x][i];
return x;
}
int main()
{
cin>>n;
for(int i=1,x,y;i<n;i++) cin>>x>>y,add(x,y),add(y,x);
dfs(1,0),cin>>m;
for(int i=1,x,y,len,LCA;i<=m;i++){
cin>>x>>y;
if(dep[x]<dep[y]) swap(x,y);
LCA=lca(x,y),len=dep[x]+dep[y]-2*dep[LCA];
if(len&1) cout<<0;
else{
len>>=1;
int mid=find(x,len);
if(mid==x) cout<<n;
else if(mid==LCA) cout<<size[1]-size[find(x,len-1)]-size[find(y,len-1)];
else cout<<size[mid]-size[find(x,len-1)];
}
cout<<endl;
}
}