#include "bits/stdc++.h" #include #include using namespace __gnu_pbds; using namespace std; // clang-format off #ifndef ONLINE_JUDGE #include "debug.h" #else #define debug(...) #endif using ll = long long; using str = string; using AR2 = array; template using oset = tree, rb_tree_tag, tree_order_statistics_node_update>; template using vec = vector; template using vvec = vec>; template using vvvec = vec>; template using vac = vec>; template using vvac = vec>; // template using priority_queue_min = priority_queue, greater>; #define sz(x) int((x).size()) #define all(x) begin(x), end(x) #define rall(x) x.rbegin(), x.rend() #define sor(x) sort(all(x)) #define pb push_back #define F_OR(i, a, b, s) for (int i=(a); (s)>0?i<(int)(b):i>(int)(b); i+=(s)) #define F_OR1(e) F_OR(i, 0, e, 1) #define F_OR2(i, e) F_OR(i, 0, e, 1) #define F_OR3(i, b, e) F_OR(i, b, e, 1) #define F_OR4(i, b, e, s) F_OR(i, b, e, s) #define GET5(a, b, c, d, e, ...) e #define F_ORC(...) GET5(__VA_ARGS__, F_OR4, F_OR3, F_OR2, F_OR1) #define FOR(...) F_ORC(__VA_ARGS__)(__VA_ARGS__) #define E_ACH2(x, a) for (auto& x: a) #define E_ACH3(x, y, a) for (auto& [x, y]: a) #define E_ACH4(x, y, z, a) for (auto& [x, y, z]: a) #define E_ACHC(...) GET5(__VA_ARGS__, E_ACH4, E_ACH3, E_ACH2) #define EACH(...) E_ACHC(__VA_ARGS__)(__VA_ARGS__) #define SUBMASKS(t, s) for (ll t = (s); t >= 0; t = (t == 0 ? -1 : (t - 1) & (s))) #define MIN(v) *min_element(all(v)) #define MAX(v) *max_element(all(v)) constexpr int popcount(int x) { return __builtin_popcount(x); } constexpr int bitlength(int x) { return x == 0 ? 0 : 31 - __builtin_clz(x); } ll cdiv(ll a, ll b) { return a/b + ((a^b) > 0 && a % b); }; ll fdiv(ll a, ll b) { return a/b - ((a^b) < 0 && a % b); }; template T pop(vec &v) { T x = v.back(); v.pop_back(); return x; } template bool bounds(T a, T lo, T hi) { return lo <= a && a <= hi; } template T truemod(T x, T M) { return (x % M + M) % M; } template bool umin(T &a, const T &b) { return b < a ? a = b, 1 : 0; } template bool umax(T &a, const T &b) { return a < b ? a = b, 1 : 0; } template int lwb(vec &a, T &b) { return int(lower_bound(all(a), b) - begin(a)); } template int upb(vec &a, T &b) { return int(upper_bound(all(a), b) - begin(a)); } template void removeDupes(vec &v) { sort(all(v)); v.erase(unique(all(v)), end(v)); } template void eraseOne(T &t, U &u) { auto it = t.find(u); assert(it != end(t)); t.erase(it); } template T firstTrue(T lo, T hi, U f) { ++hi; assert(lo <= hi); while (lo < hi) { T mi = lo + (hi-lo) / 2; f(mi) ? hi = mi : lo = mi + 1; } return lo; } template T lastTrue(T lo, T hi, U f) { --lo; assert(lo <= hi); while (lo < hi) { T mi = lo + (hi-lo+1) / 2; f(mi) ? lo = mi : hi = mi - 1; } return lo; } template istream &operator>>(istream &s, array& v) { FOR(sz(v)) s >> v[i]; return s; } template istream &operator>>(istream &s, vec& v) { FOR(sz(v)) s >> v[i]; return s; } template ostream &operator<<(ostream &s, vec& v) { FOR(sz(v)) s << (i?" ":"") << v[i]; return s; } template ostream &operator<<(ostream &s, const vec& v) { FOR(sz(v)) s << (i?" ":"") << v[i]; return s; } template void write(A x) { cout << x; } template void write(const H& h, const T&... t) { write(h); write(t...); } void print() { write("\n"); } template void print(const H& h, const T&... t) { write(h); if (sizeof...(t)) write(" "); print(t...); } void decrement() {} template void decrement(vec> &v) { EACH(row, v) EACH(x, row) --x; } template void decrement(vec> &v) { EACH(row, v) EACH(x, row) --x; } template void decrement(vec &v) { EACH(x, v) --x; } template void decrement(T &t, U &...u) { --t; decrement(u...); } template void read(T& x) { cin >> x; } template void read(T &t, U &...u) { read(t); read(u...); } #define ints(...) int __VA_ARGS__; read(__VA_ARGS__); #define int1(...) ints(__VA_ARGS__); decrement(__VA_ARGS__); #define vint(n, a) int n; cin >> n; vec a(n); cin >> a; #define vin(n, a) vec a((n)); cin >> a; #define vvin(n, m, a) vec> a((n), vec((m))); cin >> a; #define vain(n, m, a) vec> a((n)); cin >> a; #define graphin(n, m, adj) vvec adj(n); FOR(m) {int1(u, v); adj[u].pb(v); adj[v].pb(u); } #define lgraphin(n, m, adj) vvac adj(n); FOR(i, m) {int1(u, v); adj[u].pb({v,i}); adj[v].pb({u,i}); } #define wgraphin(n, m, adj) vvac adj(n); FOR(m) {int1(u, v); ints(w); adj[u].pb({v,w}); adj[v].pb({u,w}); } #define dgraphin(n, m, adj) vvec adj(n); FOR(m) {int1(u, v); adj[u].pb(v);} #define dwgraphin(n, m, adj) vvac adj(n); FOR(m) {int1(u, v, w); adj[u].pb({v, w+1});} // clang-format on struct ancestor { vector vin, vout, d; vector> adj, p; vector size; int n, t = 0, e; void dfs(int i, int v) { vin[i] = t++; p[i][0] = v, d[i] = d[v] + 1; for (int j = 1; j <= e; j++) p[i][j] = p[p[i][j - 1]][j - 1]; for (auto& j : adj[i]) if (j != v) { dfs(j, i); size[i] += size[j]; } vout[i] = t - 1; } // accepts an adjecency list. can include or exlude parents, it works either way. // constructor runs in O(nlogn) time. ancestor(vector> _adj = {}, int root = 0) : adj(_adj) , n(_adj.size()) { if (adj.empty()) return; vin.resize(n), vout.resize(n), d.assign(n, 0); size.assign(n, 1); e = ceil(log2(n)); p.assign(n, vector(e + 1)); dfs(root, root); } // returns true if i is an ancestor of j in O(1) time. bool is_ancestor(int i, int j) const { return vin[i] <= vin[j] && vout[i] >= vout[j]; } // returns the k'th ancestor of i O(logk) time. int ktha(int i, int k) const { while (k) { int j = k & -k; i = p[i][__builtin_ctz(j)]; k -= j; } return i; } // returns the LCA of i and j in O(logn) time. int lca(int i, int j) const { if (is_ancestor(i, j)) return i; if (is_ancestor(j, i)) return j; for (int k = e; k >= 0; k--) if (!is_ancestor(p[i][k], j)) i = p[i][k]; return p[i][0]; } // returns the vertex one step along the path from i to j in O(logn) time. int step(int i, int j) const { return is_ancestor(i, j) ? ktha(j, d[j] - d[i] - 1) : p[i][0]; } // returns the vertex k steps along the path from i to j in O(logn) time. int step(int i, int j, int k) const { int l = lca(i, j); return d[i] - d[l] >= k ? ktha(i, k) : ktha(j, d[i] + d[j] - 2 * d[l] - k); } // returns the number of edges between i and j in O(logn) time. int dist(int i, int j) { return d[i] + d[j] - 2 * d[lca(i, j)]; } }; int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); ints(N, Q); graphin(N, N - 1, adj); vac queries(Q); cin >> queries; decrement(queries); ancestor anc(adj); EACH(s, t, queries) { int lca = anc.lca(s, t); int d1 = anc.d[s], d2 = anc.d[t]; int dlca = anc.d[lca]; int d = d1 + d2 - 2 * dlca; if (d % 2) { print(0); continue; } d >>= 1; int cand = 0; if (d1 == d2) { // debug(d1, d2, dlca); cand += N; // cand -= anc.size[lca]; // cand -= 1; int lca_s = anc.ktha(s, d1 - dlca - 1); cand -= anc.size[lca_s]; lca_s = anc.ktha(t, d2 - dlca - 1); cand -= anc.size[lca_s]; print(cand); continue; } if (d1 < d2) { swap(d1, d2); swap(s, t); } int pivot = anc.ktha(s, d); cand = anc.size[pivot]; cand -= 1; int lca_s = anc.ktha(s, d1 - anc.d[pivot] - 1); cand -= anc.size[lca_s]; print(cand); } return 0; }