P3128
-
题目
-
分析
考虑 L C A LCA LCA
在树上对点进行差分: c n t s + + , c n t s + + , c n t l c a − − , c n t f a t h e r ( l c a ) − − cnt_s ++,cnt_s++,cnt_{lca}--,cnt_{father(lca)}-- cnts++,cnts++,cntlca−−,cntfather(lca)−−
再 d f s dfs dfs 对修改做子树和进行统计即可。
-
代码
const int SIZE = 50010; int f[SIZE][20], d[SIZE], dist[SIZE]; int ver[2 * SIZE], Next[2 * SIZE], edge[2 * SIZE], head[SIZE]; int T, n, m, tot, t, k; queue<int> q; int cnt[SIZE]; int fa[SIZE]; int vis[SIZE]; int ans; void add(int x, int y, int z) { ver[++tot] = y; edge[tot] = z; Next[tot] = head[x]; head[x] = tot; } void bfs() { q.push(1); d[1] = 1; while (q.size()) { int x = q.front(); q.pop(); for (int i = head[x]; i; i = Next[i]) { int y = ver[i]; if (d[y]) continue; d[y] = d[x] + 1; dist[y] = dist[x] + edge[i]; f[y][0] = x; for (int j = 1; j <= t; j++) f[y][j] = f[f[y][j - 1]][j - 1]; q.push(y); } } } int lca(int x, int y) { if (d[x] > d[y]) swap(x, y); for (int i = t; i >= 0; i--) if (d[f[y][i]] >= d[x]) y = f[y][i]; if (x == y) return x; for (int i = t; i >= 0; i--) if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i]; return f[x][0]; } void dfs(int x) { vis[x] = 1; for (int i = head[x]; i; i = Next[i]) { int y = ver[i]; if (vis[y]) continue; dfs(y); cnt[x] += cnt[y]; } } int main() { read(n); read(k); t = (int)(log(n) / log(2)) + 1; for (int i = 1; i <= n; i++) head[i] = d[i] = 0; tot = 0; for (int i = 1; i < n; i++) { int x, y; scanf("%d%d", &x, &y); add(x, y, 1), add(y, x, 1); } bfs(); for (int i = 1; i <= k; i++) { int s, t; read(s); read(t); cnt[s]++; cnt[t]++; cnt[lca(s, t)]--; cnt[f[lca(s,t)][0]]--; } dfs(1); for(int i =1;i <= n;i++) ans = max(ans,cnt[i]); cout << ans << endl; return 0; }
-
题型
L C A LCA LCA + 差分