Description
An n nodes existing trees, trees are a length of each side. M is given a query, asking each two nodes x, y, trees to find x, y number of nodes from the same two points.
Input
A first integer n, the tree has n points.
Next, n-1 lines each two integers a, b, from a to b indicates there is an edge.
The next line an integer m, with m represents interrogation.
The next two lines each integer of m x, y, x and y are the number interrogation from the same point.
Output
Co m rows, each row represents an integer answer queries.
Sample Input 1
7 1 2 1 3 2 4 2 5 3 6 3 7 3 1 2 4 5 2 3
Sample Output 1
0 5 1
Hint
For 30% of the data, to meet n≤50, m≤50
For 60% of the data, to meet n≤1000, m≤1000
To 100% of the data, to meet n≤100000, m≤100000
Ideas: If there is to point x, y is equal to the distance, this point must be the midpoint, or at the midpoint of the other subtree
Writing ideas:
First Japanese sentence if (x == y) ans = n
And calculating the distance dis (i.e., the number of edges on the path tree) between two points on a common ancestor LCA algorithm, the dis is odd if the node is not a midpoint, ans = 0
dis is an even number, you can find the midpoint. Found midpoint mid to climb dis / 2 of distance from the larger of the two depth point (this point is located x).
Readily occur ans = n-size [x where subtree] -size [y where subtree], but different achievements by the impact when the root node, y may not be in the mid subtree, and the branch piece in mid father
This time ans = size [mid] -size [x where subtree]
With if (mid == lca (x, y)) is true determine y in mid subtree's
(think why)
, then nothing the details.
Code:
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define maxn 100005 #define maxm 200005 #define id(x) ((x+1)>>1) using namespace std; int fir[maxn], ne[maxm], to[maxm], np; void add(int x,int y){ ne[++np] = fir[x]; fir[x] = np; to[np] = y; } int dep[maxn], fa[maxn][20], siz[maxn]; void dfs(int u,int f,int d){ dep[u] = d; siz[u] = 1; fa[u][0] = f; for(int k = 1; k <= 18; k++){ int j = fa[u][k-1]; fa[u][k] = fa[j][k-1]; } for(int i = fir[u]; i; i=ne[i]){ int v = to[i]; if(v != f) dfs(v, u, d+1), siz[u] += siz[v]; } } int jump(int u, int x) { for(int k = 18; k >= 0; k--) if((1<<k)&x) u = fa[u][k]; return u; } int jump2(int u,int anc){ for(int k = 18; k >= 0; --k) if(dep[fa[u][k]] > dep[anc]) u = fa[u][k]; return u; } int LCA(int x,int y){ x = jump(x, dep[x] - dep[y]); if(x == y) return x; for(int k = 18; k >= 0; k--) if(fa[x][k] != fa[y][k]) x = fa[x][k], y = fa[y][k]; return fa[x][0]; } int n, m; void data_in() { memset(fir, 0, sizeof(fir)); np = 0; int u, v; scanf("%d", &n); for(int i = 1; i < n; ++i) { scanf("%d%d", &u, &v); add(u, v); add(v, u); } } void solve() { dfs(1, 0, 1); int u, v, mid, dis, lca; scanf("%d", &m); while(m--) { scanf("%d%d", &u, &v); if(u==v)printf("%d\n", n); else{ if(dep[u] < dep[v]) swap(u, v); dis = dep[u] + dep[v] - 2*dep[lca = LCA(u, v)]; if(dis%2 == 0) { mid = jump(u, dis/2); u = jump2(u, mid); if(mid == lca){ v = jump2(v, mid); printf("%d\n", n - siz[u] - siz[v]); } else printf("%d\n", siz[mid] - siz[u]); } else printf("0\n"); } } } int main(){ data_in(); solve(); return 0; }