/**
题意:统计一棵树上符合条件(1.重要的点,2.不重要但是是两个重要点的lca)的点的个数
分析:1.判断是否符合条件2可以通过判断是否有两棵子树中有重要的点
2.要知道子树的情况当然可以通过爆搜解决,虽然好像题目中的一些条件使得复杂度看起来没那么糟糕,但还是会TLE
3.用dfs序结合树状数组维持子树上不重要的结点的个数,和子树的总结点数作比较
4.虽然想法不够好,但还是要勇敢一点表达,当然自己也要思路更清晰一点
*/
#include<bits/stdc++.h>
#define T__ int T;scanf("%d",&T);while(T--)
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
int kase,n,q,m,ans;
int head[maxn],tot;
struct Edge{int to,nxt;}edge[maxn<<1];///下次还是乖乖写*2吧 OTZ OTZ OTZ
int in[maxn],out[maxn],idx,f[maxn];///fa[]
int unimp[maxn];
int bit[maxn];
inline void addedge(int a,int b){///从1开始,head[]初始为0
edge[++tot].to=b;
edge[tot].nxt=head[a];
head[a]=tot;
}
inline void dfs(int u,int fa){
in[u]=++idx;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==fa) continue;
f[v]=u;
dfs(v,u);
}
out[u]=idx;
}
inline void ins(int x,int y){
for(;x<=n;x+=lowbit(x))
bit[x]+=y;
}
inline int get(int x){
int rst=0;
for(;x;x-=lowbit(x))
rst+=bit[x];
return rst;
}
inline bool check(int u){//不是两个重结点的lca
int cnt=0;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==f[u]) continue;
if(get(out[v])-get(in[v]-1)!=out[v]-in[v]+1){
if(++cnt==2) return false;
}
}
return true;
}
inline void init(){
tot=0;
// memset(head,0,sizeof(head));
// memset(bit,0,sizeof bit);
memset(head,0,sizeof(int)*(n+1));///faster
memset(bit,0,sizeof(int)*(n+1));
}
int main(){
#ifdef _DEBUG
freopen("data.in","r",stdin);
#endif // _DEBUG
T__{
init();
scanf("%d%d",&n,&q);
int a,b;
for(int i=1;i<n;i++){
scanf("%d%d",&a,&b);
addedge(a,b);
addedge(b,a);
}
printf("Case #%d:\n",++kase);
idx=0;dfs(1,0);///处理出dfs序和fa[]
for(int i=1;i<=q;i++){
scanf("%d",&m);
for(int j=1;j<=m;j++){
scanf("%d",unimp+j);
ins(in[unimp[j]],+1);
}
ans=n;
for(int j=1;j<=m;j++){
ans-=check(unimp[j]);
}
printf("%d\n",ans);
for(int j=1;j<=m;j++){///恢复
ins(in[unimp[j]],-1);
}
}
}
return 0;
}
HDU - 5927 Auxiliary Set 链式前向星、dfs序+树状数组维护子树上结点数
最新推荐文章于 2020-02-02 10:41:22 发布