题目大意:给你一棵有n个节点的树。再给你m个询问,每次询问A,B。问你树上到A,B距离相等的点有几个。
这场DIV2为何这么水 = =而且我竟然没报名参赛。。。
这题直接用倍增LCA即可
用son[]表示子节点个数
求出A B的链长度
然后求出链的中点X
这里分类讨论一下
dep[A]==dep[B]
ans=n-A跳到X的子树-B跳到X的子树
dep[A]!=dep[B]
ans=son[x]-B跳到X的子树
然后就弄完了
#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
struct line
{
int s,t;
int next;
}a[1000001];
int head[500001];
int edge;
inline void add(int s,int t)
{
a[edge].next=head[s];
head[s]=edge;
a[edge].s=s;
a[edge].t=t;
}
bool v[500001];
int deep[500001];
int ans[500001][22];
inline void bfs(int r)
{
int i,j;
deep[r]=1;
for(i=0;i<=21;i++)
ans[r][i]=r;
queue <int>Q;
while(!Q.empty())
Q.pop();
Q.push(r);
v[r]=true;
while(!Q.empty())
{
int d=Q.front();
Q.pop();
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(!v[t])
{
v[t]=true;
Q.push(t);
deep[t]=deep[d]+1;
ans[t][0]=d;
int dt;
long long dc;
for(j=1;j<=21;j++)
{
dt=ans[t][j-1];
ans[t][j]=ans[dt][j-1];
}
}
}
}
}
int son[100001];
inline void dfs(int d)
{
int i;
for(i=head[d];i!=0;i=a[i].next)
{
int t=a[i].t;
if(t!=ans[d][0])
{
dfs(t);
son[d]+=son[t];
}
}
son[d]++;
}
inline int swim(int x,int y)
{
while(deep[x]!=deep[y])
{
int i=0;
while(deep[ans[y][i]]>deep[x])
i++;
if(i!=0)
i--;
y=ans[y][i];
}
return y;
}
inline int swimx(int x,int y)
{
int i=1;
for(int pt=1;pt<=22;pt++)
i=i*2;
int pt=22;
while(x!=0)
{
while(i>x)
{
i/=2;
pt--;
}
y=ans[y][pt];
x-=i;
}
return y;
}
inline int lca(int x,int y)
{
if(deep[x]>deep[y])
{
int t=x;
x=y;
y=t;
}
y=swim(x,y);
int i=21;
while(x!=y)
{
while(ans[x][i]==ans[y][i]&&i>0)
i--;
x=ans[x][i];
y=ans[y][i];
}
return x;
}
int fa[100001];
inline int find(int x)
{
if(fa[x]!=x)
fa[x]=find(fa[x]);
return fa[x];
}
int main()
{
int n,m;
scanf("%d",&n);
int i,s,t;
for(i=1;i<=n-1;i++)
{
scanf("%d%d",&s,&t);
edge++;
add(s,t);
edge++;
add(t,s);
}
bfs(1);
dfs(1);
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%d%d",&s,&t);
if(s==t)
printf("%d\n",n);
else
{
if(deep[s]>deep[t])
{
int xt=s;
s=t;
t=xt;
}
int tx=lca(s,t);
int len=0;
if(tx==s)
len=deep[t]-deep[s];
else
len=deep[s]-deep[tx]+deep[t]-deep[tx];
if(len%2==1)
printf("0\n");
else if(deep[s]!=deep[t])
{
int yy=swimx(len/2-1,t);
int anst=son[ans[yy][0]]-son[yy];
printf("%d\n",anst);
}
else if(deep[s]==deep[t])
{
int yy=swimx(len/2-1,t);
int xx=swimx(len/2-1,s);
int anst=n-son[yy]-son[xx];
printf("%d\n",anst);
}
}
}
return 0;
}