虚树

#include<set>
#include<map>
#include<stack>
#include<ctime>
#include<cmath>
#include<queue>
#include<cstdio>
#include<vector>
#include<climits>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
int read(){
	bool f=0;int x=0;char c=getchar();
	while(c<'0'||'9'<c){if(c=='-')f=1;c=getchar();}
	while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return !f?x:-x;
}
#define MAXN 500000
#define INF 1000000000000000ll
struct Edge{
	int v,nxt;	
}edge[2*MAXN+5];
int ecnt,head[MAXN+5];
vector<int> G[MAXN+5];
inline void Addedge(int u,int v){
	edge[++ecnt]=(Edge){v,head[u]},head[u]=ecnt;
	edge[++ecnt]=(Edge){u,head[v]},head[v]=ecnt;
	return ;
}
inline void addedge(int u,int v){
	G[u].push_back(v);
	G[v].push_back(u);
	//printf("%d %d\n",u,v);
	return ;
}
int ncnt,fa[MAXN+5],dep[MAXN+5],siz[MAXN+5],Maxson[MAXN+5],dfn[MAXN+5],top[MAXN+5];
void DFS1(int u){
	siz[u]=1;
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].v;
		if(v==fa[u]) continue;
		fa[v]=u,dep[v]=dep[u]+1;
		DFS1(v),siz[u]+=siz[v];
		if(siz[v]>siz[Maxson[u]])
			Maxson[u]=v;
	}
	return ;
}
void DFS2(int u,int t){
	dfn[u]=++ncnt,top[u]=t;
	if(!Maxson[u]) return ;
	DFS2(Maxson[u],t);
	for(int i=head[u];i;i=edge[i].nxt){
		int v=edge[i].v;
		if(v==fa[u]||v==Maxson[u]) continue;
		DFS2(v,v);
	}
	return ;
}
int LCA(int u,int v){
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]) swap(u,v);
		u=fa[top[u]];
	}
	if(dep[u]>dep[v]) swap(u,v);
	return u;
}
int tp,S[MAXN+5];
void Insert(int u){
	int Lca=LCA(u,S[tp]);
	if(Lca!=S[tp]){
		while(dfn[S[tp-1]]>=dfn[Lca]) addedge(S[tp],S[tp-1]),tp--;
		if(Lca!=S[tp]) addedge(Lca,S[tp--]),S[++tp]=Lca;
	}
	if(S[tp]!=u) S[++tp]=u;
	return ;
}
bool vis[MAXN+5];
int f[MAXN+5],cnt[MAXN+5];
void Dfs(int u,int pre){
	LL sum=0;
	f[u]=0,cnt[u]=0;
	for(int i=0;i<int(G[u].size());i++){
		int v=G[u][i];
		if(v==pre) continue;
		Dfs(v,u),f[u]+=f[v],sum+=cnt[v];
	}
	if(vis[u]) cnt[u]=1,f[u]+=sum;
	else if(sum>1) cnt[u]=0,f[u]++;
	else cnt[u]=sum;
	G[u].clear();
	return ;
}
/*
int dp(int u){
    int ans=0,sum=0;
    go(u)ans+=dp(v),sum+=b[v];
    if(fg[u])b[u]=1,ans+=sum;
    else if(sum>1)b[u]=0,++ans;
    else b[u]=sum;return fi[u]=0,ans;
}
*/
int a[MAXN+5];
bool cmp(int a,int b){return dfn[a]<dfn[b];}
int main(){
	int n=read();
	for(int i=1;i<n;i++){
		int u=read(),v=read();
		Addedge(u,v);
	}
	DFS1(1),DFS2(1,1);
	int m=read();
	for(int t=1;t<=m;t++){
		int k=read();
		for(int i=1;i<=k;i++)
			a[i]=read(),vis[a[i]]=1;
		for(int i=1;i<=k;i++)
			if(vis[fa[a[i]]]){
				puts("-1");
				goto Break;
			}
		sort(a+1,a+k+1,cmp);
		tp=1,S[tp]=1;
		for(int i=1;i<=k;i++)
			Insert(a[i]);
		while(tp>1)
			addedge(S[tp],S[tp-1]),tp--;
		Dfs(1,0),printf("%d\n",f[1]);
		Break:;
		for(int i=1;i<=k;i++)
			vis[a[i]]=0;
	}
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值