题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5927
题目大意:
(补题解中先把思路码上)
解题思路:
这里被memset坑了,注意到如果有10W个点,10W个询问,每次memset一次肯定爆炸。
先根据根节点建下树。
这里注意到不重要的点很少,我们从不重要点的遍历,如果不重要的点下面的两个子树中有两个重要的点,那么就将它变为重要的点,那么该如何节省memeset呢,我将非重要的点标记为了问题编号,对于第i个问题,非重要的点编号就是i。
对于一个编号为i的点。
如果遍历了这个点,且这个点能变成重要的点,那么把它编号变为0。
如果它不能变成重要的点,但是它下面有一个重要的点,那么它的编号为100005+i
如果它不能变成重要的点,它下面也没有重要的点,那么它的编号为为
-i。
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
#include <set>
#include <functional>
#define RI(N) scanf("%d",&(N))
#define RII(N,M) scanf("%d %d",&(N),&(M))
#define RIII(N,M,K) scanf("%d %d %d",&(N),&(M),&(K))
#define mem(a) memset((a),0,sizeof(a))
using namespace std;
const int inf=1e9;
const int inf1=-1*1e9;
double EPS=1e-10;
typedef long long LL;
vector<int> G[100005];
vector<int> real_G[100005];
vector<int> unimpotant;
int ans[100005],ans1=0;
int vis[100005],n,q;
int qqq;
void dfs(int x)
{
for(int i=0; i<G[x].size(); i++)
{
int de=G[x][i];
if(!vis[de])
{
vis[de]=1;
real_G[x].push_back(de);
dfs(de);
}
}
return ;
}
void jianshu()
{
for(int i=0; i<=n+1; i++)
vis[i]=0;
vis[1]=1;
dfs(1);
}
int dfs1(int x)
{
int summ=0;
for(int i=0; i<real_G[x].size(); i++)
{
int d=real_G[x][i];
if((ans[d]==qqq)) summ+=dfs1(d);
else if(ans[d]!=-qqq) summ++;
if(summ>=2) break;
}
if(summ>=2)
{
ans[x]=0;
return 1;
}
if(summ>=1)
{
ans[x]=100005+qqq;
return 1;
}
ans[x]=-qqq;
return 0;
}
void solve()
{
for(int i=0; i<unimpotant.size(); i++)
{
int x=unimpotant[i];
if(ans[x]==qqq) dfs1(x);
if(ans[x]!=(-qqq)&&ans[x]!=100005+qqq) ans1++;
}
/*for(int i=1;i<=n;i++)
if(ans[i]==0) cout<<"im = "<<i<<endl;*/
printf("%d\n",ans1);
}
int main()
{
int T,cas=1;
RI(T);
while(T--)
{
printf("Case #%d:\n",cas++);
RII(n,q);
for(int i=0; i<=n+1; i++)
{
G[i].clear();
real_G[i].clear();
}
for(int i=1; i<=n-1; i++)
{
int x,y;
RII(x,y);
G[x].push_back(y);
G[y].push_back(x);
}
jianshu();
memset(ans,0,sizeof(int)*(n+2));
for(int i=1; i<=q; i++)
{
qqq=i;
ans1=0;
int m,x;
RI(m);
ans1+=n-m;
unimpotant.clear();
for(int j=0; j<m; j++)
{
RI(x);
unimpotant.push_back(x);
ans[x]=qqq;
}
solve();
}
}
return 0;
}