虚树+DP
DP:(f[u]) 表示 (u) 的答案,(sz[u]) 表示 (u) 向上传递的贡献(在一开始是用来记录子树中需要截断多少个关键点)。当前点是关键点,则全部截断子树中的点并令 (sz[u]=1) ,向上传递;当前点不是关键点,若底下有多个点,则把当前点去掉,若底下只有一个点,向上传递。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define R register int
using namespace std;
namespace Luitaryi {
inline int g() { R x=0,f=1;
register char s; while(!isdigit(s=getchar())) f=s=='-'?-1:f;
do x=x*10+(s^48); while(isdigit(s=getchar())); return x*f;
} const int N=100010;
int n,m,k;
int vr[N<<1],nxt[N<<1],fir[N],cnt,num,d[N],pre[N],top[N],dfn[N],sz[N],son[N];
int stk[N],h[N],f[N],ans[N]; bool vis[N];
inline void add(int u,int v)
{vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
inline void dfs(int u) {
dfn[u]=++num,sz[u]=1;
for(R i=fir[u];i;i=nxt[i]) {
R v=vr[i];
if(dfn[v]) continue;
d[v]=d[u]+1,pre[v]=u;
dfs(v);
sz[u]+=sz[v];
if(sz[son[u]]<sz[v]) son[u]=v;
}
}
inline void dfs2(int u,int tp) {
top[u]=tp;
if(son[u]) dfs2(son[u],tp);
for(R i=fir[u];i;i=nxt[i]) {
R v=vr[i];
if(top[v]) continue;
dfs2(v,v);
}
}
inline int lca(int u,int v) {
while(top[u]!=top[v]) {
if(d[top[u]]<d[top[v]]) swap(u,v);
u=pre[top[u]];
} return d[u]<d[v]?u:v;
}
inline bool cmp(const int& a,const int& b)
{return dfn[a]<dfn[b];}
inline void dp(int u) {
f[u]=sz[u]=0;
for(R i=fir[u];i;i=nxt[i]) {
R v=vr[i];
dp(v);
f[u]+=f[v];
sz[u]+=sz[v];
}
if(vis[u]) f[u]+=sz[u],sz[u]=1;
else if(sz[u]>1) sz[u]=0,++f[u];
}
inline void main() {
n=g();
for(R i=1,u,v;i<n;++i)
u=g(),v=g(),add(u,v),add(v,u);
d[1]=1,dfs(1),dfs2(1,1);
memset(fir,0,sizeof fir);
m=g(); while(m--) {
k=g();
for(R i=1;i<=k;++i) vis[h[i]=g()]=true;
for(R i=1;i<=k;++i) if(vis[pre[h[i]]])
{puts("-1"); goto end;}
sort(h+1,h+k+1,cmp);
fir[1]=cnt=0; R top;
stk[top=1]=1;
for(R i=1+(h[1]==1),l;i<=k;++i) {
l=lca(h[i],stk[top]);
if(l!=stk[top]) {
while(dfn[l]<dfn[stk[top-1]])
add(stk[top-1],stk[top]),--top;
if(dfn[l]>dfn[stk[top-1]])
fir[l]=0,
add(l,stk[top]),stk[top]=l;
else
add(l,stk[top]),--top;
}
fir[h[i]]=0,stk[++top]=h[i];
}
for(R i=1;i<top;++i)
add(stk[i],stk[i+1]);
dp(1);
printf("%d
",f[1]);
end:for(R i=1;i<=k;++i) vis[h[i]]=0;
}
}
} signed main() {Luitaryi::main(); return 0;}
2020.01.18