说一下为什么按LCA深度从深到浅贪心是对的。我们可以直观感受一下,一条的路径会影响以这个lca为根的这颗树中的链,而深度越深,影响范围越小,所以先选影响范围小的路径。
#includeusing 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 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); }}