Files
python/TangDou/AcWing/LCA/P3128.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

93 lines
2.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10, M = N << 1;
int n, k;
//链式前向星
int e[M], h[N], idx, w[M], ne[M];
void add(int a, int b, int c = 0) {
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}
//树上差分模板题【点权】
int depth[N], f[N][25];
int dlt[N];
// 倍增2^k,计算k的办法
// T = log(n) / log(2) + 1;
const int T = 22;
//倍增求 a,b的最近公共祖先
void bfs(int root) {
queue<int> q;
q.push(root);
depth[root] = 1;
while (q.size()) {
int u = q.front();
q.pop();
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (depth[j]) continue;
depth[j] = depth[u] + 1;
f[j][0] = u;
for (int k = 1; k <= T; k++) f[j][k] = f[f[j][k - 1]][k - 1];
q.push(j);
}
}
}
int lca(int a, int b) {
if (depth[a] < depth[b]) swap(a, b);
for (int k = T; k >= 0; k--)
if (depth[f[a][k]] >= depth[b])
a = f[a][k];
if (a == b) return a;
for (int k = T; k >= 0; k--)
if (f[a][k] != f[b][k])
a = f[a][k], b = f[b][k];
return f[a][0];
}
//前缀和
void dfs(int u, int fa) {
for (int i = h[u]; ~i; i = ne[i]) {
int j = e[i];
if (j == fa) continue;
dfs(j, u);
//遍历完j后,dlt[j]已经被填充好,可以合并计算dlt[u]了
dlt[u] += dlt[j];
}
}
int main() {
memset(h, -1, sizeof h);
scanf("%d %d", &n, &k);
for (int i = 1; i < n; i++) { // n-1条边
int a, b;
scanf("%d %d", &a, &b);
add(a, b), add(b, a);
}
//预处理出lca需要的depth数组+f数组(倍增位置数组)
bfs(1);
// k条运输牛奶的路线
for (int i = 1; i <= k; i++) {
int a, b;
scanf("%d %d ", &a, &b);
int lc = lca(a, b);
//点差分
dlt[a]++;
dlt[b]++;
//提前就把1减出去了
dlt[lc]--;
dlt[f[lc][0]]--;
}
//利用前缀和合并差分,此时dlt数组的含义已经不是差分了,而是结果数组了
dfs(1, 0);
int res = 0; //找出结果数组中的最大值即是答案
for (int i = 1; i <= n; i++) res = max(res, dlt[i]);
printf("%d\n", res);
return 0;
}