标签:max data lse 一个 event 代码 cst ems style
Description
现有一棵 n 个节点的棵, 树上每条边的长度均为 1。 给出 m 个询问, 每次询问两个节点 x,y, 求树上到 x,y 两个点距离相同的节点数量。
Input
第一个整数 n, 表示树有 n 个点。
接下来 n-1 行每行两整数 a, b, 表示从 a 到 b 有一条边。
接下来一行一个整数 m, 表示有 m 个询问。
接下来 m 行每行两整数 x, y, 询问到 x 和 y 距离相同的点的数量。
Output
共 m 行, 每行一个整数表示询问的答案。
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
#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; }
标签:max data lse 一个 event 代码 cst ems style
原文地址:https://www.cnblogs.com/de-compass/p/11521247.html