Codeforces 519

E - A and B and Lecture Rooms

Problem

A and B are preparing themselves for programming contests.

The University where A and B study is a set of rooms connected by corridors. Overall, the University has n rooms connected by n - 1 corridors so that you can get from any room to any other one by moving along the corridors. The rooms are numbered from 1 to n.

Every day А and B write contests in some rooms of their university, and after each contest they gather together in the same room and discuss problems. A and B want the distance from the rooms where problems are discussed to the rooms where contests are written to be equal. The distance between two rooms is the number of edges on the shortest path between them.

As they write contests in new rooms every day, they asked you to help them find the number of possible rooms to discuss problems for each of the following m days.

Input

The first line contains integer n (1 ≤ n ≤ 10) — the number of rooms in the University.

The next n - 1 lines describe the corridors. The i-th of these lines (1 ≤ i ≤ n - 1) contains two integers a and b (1 ≤ a, b ≤ n), showing that the i-th corridor connects rooms a and b.

The next line contains integer m (1 ≤ m ≤ 10) — the number of queries.

Next m lines describe the queries. The j-th of these lines (1 ≤ j ≤ m) contains two integers x and y (1 ≤ x, y ≤ n) that means that on the j-th day A will write the contest in the room x, B will write in the room y.

Output

In the i-th (1 ≤ i ≤ m) line print the number of rooms that are equidistant from the rooms where A and B write contest on the i-th day.

Examples

Input
4
1 2
1 3
2 4
1
2 3
Output
1
Input
4
1 2
2 3
2 4
2
1 2
1 3
Output
0
2

Note

in the first sample there is only one room at the same distance from rooms number 2 and 3 — room number 1.

解题思路:

先说一下题意

给你一棵树(图),然后再询问,每次询问给你两个点,问你有多少个点到这两个点的距离相等

这是一道LCA的变种题,可以想到,这两个点的中点一定在这两个点的最短路上,也就是一定在他们求LCA的路径上

然后再考虑

1.如果两个点之间点的个数是偶数,那么答案就是零,无法找到到他俩距离相等的点

2.如果两个点之间的距离是奇数

  2.1如果两者的深度相同,那么数量就是所有点除去他俩的LCA的子树中的他俩在的子树所有点的个数

    N-SIZE(a所在的LCA的 子树)-SIZE(b所在的LCA的 子树)

  2.2如果两者深度不同,答案就是所有点除去他俩中点的子树所有点的个数

    N-SIZE(中点mid的 子树)

知道求法之后,我们只需要建立一个SIZE数组来记录每一个点的子树上的点的个数之后,就非常好计算了

关于中点,我们就模拟倍增法来找他们的中点

代码如下:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3
  4 const int N=1e5+7;
  5 //bool vis[N];
  6 int n,m,tot,tol;
  7 int depth[N];
  8 int head[N];
  9 int sizes[N];
 10 int father[N][25];
 11 struct node
 12 {
 13     int v;
 14     int next;
 15 } e[N<<1];
 16
 17 void add(int u,int v)
 18 {
 19     e[tol].v=v;
 20     e[tol].next=head[u];
 21     head[u]=tol++;
 22 }
 23
 24
 25 void dfs(int u, int fa)
 26 {
 27     for(int i=head[u]; i; i=e[i].next)
 28     {
 29         int v=e[i].v;
 30         if(v!=fa)
 31         {
 32             father[v][0]=u;
 33             depth[v]=depth[u]+1;
 34             dfs(v,u);
 35             //记录子树点的个数
 36             sizes[u]+=sizes[v];
 37         }
 38     }
 39 }
 40
 41 void initfa()
 42 {
 43     for(int j=1; j<=20; ++j)
 44         for(int i=1; i<=n; ++i)
 45             father[i][j]=father[father[i][j-1]][j-1];
 46 }
 47
 48 inline int lca(int u,int v)
 49 {
 50     if(depth[u]<depth[v])
 51         swap(u,v);
 52     int d=depth[u]-depth[v];
 53     for(int i=0; i<=20; ++i)
 54         if((1<<i)&d)
 55             u=father[u][i];
 56     if(u==v)
 57         return u;
 58     for(int i=20; i>=0; --i)
 59     {
 60         if(depth[father[u][i]]<=0)
 61             continue;
 62         if(father[u][i]!=father[v][i])
 63         {
 64             u=father[u][i];
 65             v=father[v][i];
 66         }
 67     }
 68     return father[u][0];
 69 }
 70
 71 int main()
 72 {
 73     std::ios::sync_with_stdio(false);
 74     int T;
 75     int x,y;
 76     cin>>n;
 77
 78         tot=0;
 79         tol=1;
 80         for(int i=1; i<n; ++i)
 81         {
 82             cin>>x>>y;
 83             add(x,y);
 84             add(y,x);
 85         }
 86         for(int i=1; i<=n; ++i)
 87             sizes[i]=1;
 88         dfs(1,0);
 89         initfa();
 90         cin>>m;
 91         int u,v;
 92         for(int i=0; i<m; ++i)
 93         {
 94             cin>>u>>v;
 95             if(depth[u]<depth[v])
 96                 swap(u,v);
 97             if((depth[u]+depth[v]-2*(lca(u,v)))&1)
 98             {
 99                 cout<<"0"<<endl;
100                 continue;
101             }
102             int lc=lca(u,v),x=u;
103             int p=(depth[u]+depth[v]-2*depth[lc])/2-1;
104             //模拟倍增找中点
105             for(int i=20; i>=0; --i)
106                 if(p&(1<<i))
107                     u=father[u][i];
108             if(depth[x]==depth[v])
109             {
110                 p=depth[v]-depth[lc]-1;
111                 for(int i=20; i>=0; --i)
112                     if(p&(1<<i))
113                         v=father[v][i];
114                 cout<<n-sizes[u]-sizes[v]<<endl;
115                 //printf("%d\n",n-sizes[u]-sizes[v]);
116             }
117             else
118                 cout<<sizes[father[u][0]]-sizes[u]<<endl;
119                 //printf("%d\n",sizes[father[u][0]]-sizes[u]);
120         }
121
122     return 0;
123 }
12-16 18:12