1.题面
http://acm.hdu.edu.cn/showproblem.php?pid=5927
2.题意
这个题意是抄来的,不想概括了:
给一棵树,然后每次询问时给出哪些点是不重要的点,让求这棵树上重要的点以及是两个不同的重要的点的lca一共有多少个;
3.思路
每个初始状态下非重要的点是否能成为一个重要的点只取决于他的儿子,如果他的儿子
1.是重要的点
2.的子孙中有重要的点
则该儿子是一个有效的节点。
如果一个初始状态下非重要节点的有效节点个数大于等于2则该节点可以从非重要节点变成重要节点
4.代码
/*****************************************************************
> File Name: cpp_acm.cpp
> Author: Uncle_Sugar
> Mail: uncle_sugar@qq.com
> Created Time: Sat 08 Oct 2016 19:26:55 CST
*****************************************************************/
# include <cstdio>
# include <cstring>
# include <cctype>
# include <cmath>
# include <cstdlib>
# include <climits>
# include <iostream>
# include <iomanip>
# include <set>
# include <map>
# include <vector>
# include <stack>
# include <queue>
# include <algorithm>
using namespace std;
# define rep(i,a,b) for (i=a;i<=b;i++)
# define rrep(i,a,b) for (i=b;i>=a;i--)
# define mset(aim, val) memset(aim, val, sizeof(aim))
template<class T>void PrintArray(T* first,T* last,char delim=' '){
for (;first!=last;first++) cout << *first << (first+1==last?'\n':delim);
}
/*
1.see the size of the input data before you select your algorithm
2.cin&cout is not recommended in ACM/ICPC
3.pay attention to the size you defined, for instance the size of edge is double the size of vertex
*/
const int debug = 1;
const int size = 10 + 100000;
const int INF = INT_MAX>>1;
typedef long long ll;
struct Edge{
int to, nxt;
}edge[2*size];
int head[size], tot;
void addedge(int from, int to){
edge[tot].to = to;edge[tot].nxt = head[from];head[from] = tot++;
}
void init(){
memset(head, -1, sizeof(head));
tot = 0;
}
int dep[size], fa[size], sonsum[size], _sonsum[size];
void dfs(int rt){
sonsum[rt] = 0;
for (int e = head[rt]; ~e; e = edge[e].nxt){
int to = edge[e].to;
if (to != fa[rt]){
fa[to] = rt;dep[to] = dep[rt] + 1;
sonsum[rt]++;
dfs(to);
}
}
}
int unimpt[size];
bool cmp(int x, int y){
return dep[x] > dep[y];
}
int stk[size], stklen;
int main()
{
/*std::ios::sync_with_stdio(false);cin.tie(0);*/
int T;
scanf("%d", &T);
for (int cas = 1; cas <= T; cas++){
init();
int n, q;
scanf("%d%d", &n, &q);
for (int i = 0; i < n-1; i++){
int a, b;
scanf("%d%d", &a, &b);
addedge(a, b);
addedge(b, a);
}
fa[1] = -1;dep[1] = 0;
dfs(1);
printf("Case #%d:\n", cas);
while (q--){
int s, t;
scanf("%d", &s);
for (int i = 0; i < s; i++) scanf("%d", unimpt + i);
sort(unimpt, unimpt + s, cmp);
int ans = n - s;
for (int i = 0; i < s; i++){
int t = unimpt[i];
int flag = sonsum[t] - _sonsum[t];
//# cout << "cur flag = " << t << " " << flag << endl;
if (flag >= 2){
ans++;
//# cout << t << " isok " << endl;
}else if (flag == 0){
_sonsum[fa[t]]++;
stk[stklen++] = fa[t];
}
}
while (stklen){
_sonsum[stk[--stklen]] = 0;
}
printf("%d\n", ans);
}
}
return 0;
}