HDU - 5927 Auxiliary Set dfs序+瞎搞

題目鏈接: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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章