cqyz oj | trees inquiry | recent common ancestor

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;
}
View Code

 

 

Guess you like

Origin www.cnblogs.com/de-compass/p/11521247.html