题目链接:点击打开链接
题意:
给定n个点的树。
下面n-1行给出树
Q个询问。
每次询问 (u,v)问树上有多少个点到u点距离=到v点距离
思路:
首先这两个点的距离必须是偶数,若为奇数答案就是0
然后用lca找到中间节点即可。
trick : u==v ans = n
#include"cstdio"
#include"iostream"
#include"queue"
#include"algorithm"
#include"set"
#include"queue"
#include"cmath"
#include"string.h"
#include"vector"
using namespace std;
template <class T>
inline bool rd(T &ret) {
char c; int sgn;
if (c = getchar(), c == EOF) return 0;
while (c != '-' && (c<'0' || c>'9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
template <class T>
inline void pt(T x) {
if (x <0) {
putchar('-');
x = -x;
}
if (x>9) pt(x / 10);
putchar(x % 10 + '0');
}
#define N 100500
struct Edge{
int from, to, nex;
}edge[2 * N];
int head[N], edgenum, fa[N][20], dep[N], siz[N]; //fa[i][x] 是i的第2^x个父亲(如果超过范围就是根)
void add(int u, int v){
Edge E = { u, v, head[u] };
edge[edgenum] = E;
head[u] = edgenum++;
}
void bfs(int root){
queue<int> q;
fa[root][0] = root; dep[root] = 0; siz[root] = 0;
q.push(root);
while (!q.empty()){
int u = q.front(); q.pop();
for (int i = 1; i<20; i++)fa[u][i] = fa[fa[u][i - 1]][i - 1];
for (int i = head[u]; ~i; i = edge[i].nex){
int v = edge[i].to; if (v == fa[u][0])continue;
dep[v] = dep[u] + 1; fa[v][0] = u;
q.push(v);
}
}
}
void dfs(int u, int f){
siz[u] = 1;
for (int i = head[u]; ~i; i = edge[i].nex){
int v = edge[i].to; if (v == f)continue;
dfs(v, u);
siz[u] += siz[v];
}
}
int Lca(int x, int y){
if (dep[x]<dep[y])swap(x, y);
for (int i = 0; i<20; i++)if ((dep[x] - dep[y])&(1 << i))x = fa[x][i];
if (x == y)return x;
for (int i = 19; i >= 0; i--)if (fa[x][i] != fa[y][i])x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
void init(){ memset(head, -1, sizeof head); edgenum = 0; }
int n, m;
int go(int D, int x){
while (D){
int z = log10(1.0*D) / log10(2.0);
x = fa[x][z];
D -= 1 << z;
}
return x;
}
int main(){
rd(n);
init();
for (int i = 1, u, v; i < n; i++){
rd(u); rd(v);
add(u, v); add(v, u);
}
bfs(1);
dfs(1, 1);
rd(m);
int x, y;
while (m--){
rd(x); rd(y);
if (x == y){ pt(n); putchar('\n'); continue; }
if (dep[x]>dep[y])swap(x, y);
int l = Lca(x, y);
int len = dep[x] - dep[l] + dep[y] - dep[l];
if (len & 1){
putchar('0');
}
else {
len = len / 2 - 1;
int a = go(len, y), b = fa[a][0];
if (b == l){
pt(n - siz[a] - siz[go(len, x)]);
}
else pt(siz[b] - siz[a]);
}
putchar('\n');
}
return 0;
}