说一下为什么按LCA深度从深到浅贪心是对的。我们可以直观感受一下,一条的路径会影响以这个lca为根的这颗树中的链,而深度越深,影响范围越小,所以先选影响范围小的路径。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;
int head[maxn], Next[maxn * 2], ver[maxn * 2], tot, f[maxn][20];
int deep[maxn], t;
struct Edge {
int u, v, lca, lca_deep;
bool operator < (const Edge& rhs) const {
return lca_deep > rhs.lca_deep;
}
};
Edge a[maxn];
bool v[maxn];
void add(int x, int y) {
ver[++tot] = y;
Next[tot] = head[x];
head[x] = tot;
}
queue<int> q;
void bfs() {
deep[1] = 1;
q.push(1);
while(!q.empty()) {
int x = q.front();
q.pop();
for (int i = head[x]; i; i = Next[i]) {
int y = ver[i];
if(deep[y]) continue;
deep[y] = deep[x] + 1;
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 query(int x, int y) {
if(deep[x] > deep[y]) swap(x, y);
for (int i = t; i >= 0; i--) {
if(deep[f[y][i]] >= deep[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, int fa) {
if(v[x]) return;
v[x] = 1;
for (int i = head[x]; i; i = Next[i]) {
int y = ver[i];
if(y == fa) continue;
dfs(y, x);
}
}
int main() {
int n, m, x, y;
while(~scanf("%d%d", &n, &m)) {
t = (int)(log(n) / log(2)) + 1;
tot = 0;
for (int i = 1; i <= n; i++) {
head[i] = 0;
v[i] = 0;
for (int j = 0; j <= t; j++)
f[i][j] = 0;
deep[i] = 0;
}
// memset(head, 0, sizeof(head));
// memset(f, 0, sizeof(f));
// memset(v, 0, sizeof(v));
// memset(deep, 0, sizeof(deep));
// tot = 0;
for (int i = 1; i < n; i++) {
scanf("%d%d", &x, &y);
add(x, y);
add(y, x);
}
bfs();
int ans = 0;
for (int i = 1; i <= m; i++) {
scanf("%d%d", &a[i].u, &a[i].v);
a[i].lca = query(a[i].u, a[i].v);
a[i].lca_deep = deep[a[i].lca];
}
sort(a + 1, a + 1 + m);
for (int i = 1; i <= m; i++) {
if(!v[a[i].u] && !v[a[i].v]) {
ans++;
dfs(a[i].lca, f[a[i].lca][0]);
}
}
printf("%d\n", ans);
}
}