题意:
n
≤
1
e
5
,
∑
k
≤
1
e
5
,
q
≤
1
e
5
n\le1e5,\sum k\le1e5,q\le1e5
n≤1e5,∑k≤1e5,q≤1e5。
思路:
经过分析,外敌占领的城市只有可能是两点的
l
c
a
lca
lca或者两点之间任意一点,是哪个点无所谓,所以我们首先检查一下是否存在两个重要城市互为父子,否则的话一定有解。
由于存在大量不重要的点,所以我们按照重要的城市建立一颗虚树,让后在虚树上
d
p
dp
dp,每个点分两种情况:
(
1
)
(1)
(1)这个点是重要城市,那么他必须与所有有重要城市的儿子之间断开。
(
2
)
(2)
(2)这个点不是重要城市,那么如果儿子也没有重要城市就对答案无贡献。如果儿子有一个重要城市,那么将这个城市也变成重要城市即可,相当于标记上传了,对答案也无贡献。如果儿子有多于
1
1
1个重要城市,那么只需要将当前这个点占领即可,答案加一。
最后不要忘记清空数据,清空的时候可以再遍历一次清空即可。
// Problem: D. Kingdom and its Cities
// Contest: Codeforces - Codeforces Round #339 (Div. 1)
// URL: https://codeforces.com/problemset/problem/613/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;
//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;
int n,m;
vector<int>v[N];
int a[N],tot;
int stk[N],top;
int dfn[N],idx,fa[N][20],depth[N];
int has[N],ans;
void dfs1(int u,int f) {
fa[u][0]=f; dfn[u]=++idx;
depth[u]=depth[f]+1;
for(int i=1;i<=18;i++) fa[u][i]=fa[fa[u][i-1]][i-1];
for(auto x:v[u]) {
if(x==f) continue;
dfs1(x,u);
}
}
int lca(int a,int b) {
if(depth[a]<depth[b]) swap(a,b);
for(int i=18;i>=0;i--)
if(depth[fa[a][i]]>=depth[b])
a=fa[a][i];
if(a==b) return a;
for(int i=18;i>=0;i--)
if(fa[a][i]!=fa[b][i])
a=fa[a][i],b=fa[b][i];
return fa[a][0];
}
bool check() {
for(int i=1;i<=tot;i++) {
if(has[fa[a[i]][0]]) return true;
}
return false;
}
bool cmp(int a,int b) {
return dfn[a]<dfn[b];
}
void insert(int x) {
if(!top) stk[++top]=x;
else {
int father=lca(x,stk[top]);
while(top>1&&depth[father]<depth[stk[top-1]]) {
v[stk[top-1]].pb(stk[top]),top--;
}
if(depth[father]<depth[stk[top]]) v[father].pb(stk[top--]);
if(!top||(stk[top]!=father)) stk[++top]=father;
stk[++top]=x;
}
}
void dfs2(int u,int f) {
if(has[u]) {
int add=0;
for(auto x:v[u]) {
if(x==f) continue;
dfs2(x,u);
add+=has[x]>0;
}
ans+=add;
} else {
int add=0;
for(auto x:v[u]) {
if(x==f) continue;
dfs2(x,u);
add+=has[x]>0;
}
if(add>1) ans++;
else if(add==1) has[u]=1;
}
}
void dfs3(int u,int f) {
//printf("%d**\n",u);
has[u]=0;
for(auto x:v[u]) {
if(x==f) continue;
dfs3(x,u);
}
v[u].clear();
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
scanf("%d",&n);
for(int i=1;i<=n-1;i++) {
int a,b; scanf("%d%d",&a,&b);
v[b].pb(a); v[a].pb(b);
}
dfs1(1,0);
for(int i=1;i<=n;i++) v[i].clear();
scanf("%d",&m);
while(m--) {
scanf("%d",&tot);
for(int i=1;i<=tot;i++) scanf("%d",&a[i]),has[a[i]]=1;
if(check()) {
for(int i=1;i<=tot;i++) has[a[i]]=0;
puts("-1");
continue;
}
sort(a+1,a+1+tot,cmp); top=0; ans=0;
if(a[1]!=1) stk[++top]=1;
for(int i=1;i<=tot;i++) insert(a[i]);
while(top>1) v[stk[top-1]].pb(stk[top]),top--;
dfs2(1,0); dfs3(1,0);
printf("%d\n",ans);
}
return 0;
}
/*
*/