题目链接:点击打开链接
题意:
给定n个点的树。
下面n-1行给出树
Q个询问。
每次询问 (u,v)问树上有多少个点到u点距离=到v点距离
思路:
首先这两个点的距离必须是偶数,若为奇数答案就是0
然后用lca找到中间节点即可。
trick : u==v ans = n
#include"cstdio" #include"iostream" #include"queue" #include"algorithm" #include"set" #include"queue" #include"cmath" #include"string.h" #include"vector" using namespace std; template <class T> inline bool rd(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void pt(T x) { if (x <0) { putchar('-'); x = -x; } if (x>9) pt(x / 10); putchar(x % 10 + '0'); } #define N 100500 struct Edge{ int from, to, nex; }edge[2 * N]; int head[N], edgenum, fa[N][20], dep[N], siz[N]; //fa[i][x] 是i的第2^x个父亲(如果超过范围就是根) void add(int u, int v){ Edge E = { u, v, head[u] }; edge[edgenum] = E; head[u] = edgenum++; } void bfs(int root){ queue<int> q; fa[root][0] = root; dep[root] = 0; siz[root] = 0; q.push(root); while (!q.empty()){ int u = q.front(); q.pop(); for (int i = 1; i<20; i++)fa[u][i] = fa[fa[u][i - 1]][i - 1]; for (int i = head[u]; ~i; i = edge[i].nex){ int v = edge[i].to; if (v == fa[u][0])continue; dep[v] = dep[u] + 1; fa[v][0] = u; q.push(v); } } } void dfs(int u, int f){ siz[u] = 1; for (int i = head[u]; ~i; i = edge[i].nex){ int v = edge[i].to; if (v == f)continue; dfs(v, u); siz[u] += siz[v]; } } int Lca(int x, int y){ if (dep[x]<dep[y])swap(x, y); for (int i = 0; i<20; i++)if ((dep[x] - dep[y])&(1 << i))x = fa[x][i]; if (x == y)return x; for (int i = 19; i >= 0; i--)if (fa[x][i] != fa[y][i])x = fa[x][i], y = fa[y][i]; return fa[x][0]; } void init(){ memset(head, -1, sizeof head); edgenum = 0; } int n, m; int go(int D, int x){ while (D){ int z = log10(1.0*D) / log10(2.0); x = fa[x][z]; D -= 1 << z; } return x; } int main(){ rd(n); init(); for (int i = 1, u, v; i < n; i++){ rd(u); rd(v); add(u, v); add(v, u); } bfs(1); dfs(1, 1); rd(m); int x, y; while (m--){ rd(x); rd(y); if (x == y){ pt(n); putchar('\n'); continue; } if (dep[x]>dep[y])swap(x, y); int l = Lca(x, y); int len = dep[x] - dep[l] + dep[y] - dep[l]; if (len & 1){ putchar('0'); } else { len = len / 2 - 1; int a = go(len, y), b = fa[a][0]; if (b == l){ pt(n - siz[a] - siz[go(len, x)]); } else pt(siz[b] - siz[a]); } putchar('\n'); } return 0; }
时间: 2024-10-06 12:34:42