題目鏈接:https://vjudge.net/problem/HDU-5927
題意:給一棵樹,然後每次詢問時給出哪些點是不重要的點,讓求這棵樹上重要的點以及是兩個不同的重要的點的lca一共有多少個
題解:我們只需要看給出的每一個不重要的點是不是重要的點就可以了,如果他能是重要的點,那麼存在兩個不同的分支上有重要的點,因此對於一個分支如果全都是不重要的點,那麼我們就向上傳遞減一,代表這個分支沒了。處理點的時候可以按照dfs序進行排序
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
vector<int> v[N];
int n, q;
int son[N];
int in[N], tot;
int b[N], len;
int vis[N];
int f[N];
void dfs(int u, int fa) {
in[u] = ++tot;
f[u] = fa;
int to;
son[u] = 0;
for(int i = 0; i < v[u].size(); i++) {
to = v[u][i];
if(to == fa ) continue;
dfs(to, u);
son[u]++;
}
}
bool cmp(int x, int y) {
return in[x] > in[y];
}
int main() {
int T;
int x, y;
int ans;
int nn = 1;
scanf("%d", &T);
while(T--) {
scanf("%d %d", &n, &q);
tot = 0;
for(int i = 0; i <= n; i++) {
v[i].clear();
}
for(int i = 1; i < n; i++) {
scanf("%d %d", &x, &y);
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1, 0);
printf("Case #%d:\n", nn++);
while(q--) {
scanf("%d", &len);
for(int i = 1; i <= len; i++) scanf("%d", &b[i]);
sort(b + 1, b + 1 + len, cmp);
ans = n - len;
for(int i = 1; i <= len; i++) {
if(son[b[i]] - vis[b[i]] >= 2) ans++;
if(son[b[i]] - vis[b[i]] == 0) vis[f[b[i]]]++;
}
printf("%d\n", ans);
for(int i = 1; i <= len; i++) {
vis[f[b[i]]] = 0;
}
}
}
return 0;
}