题解 -
C
F
613
D
K
i
n
g
d
o
m
a
n
d
i
t
s
C
i
t
i
e
s
\mathrm{CF613D \ Kingdom \ and \ its \ Cities}
CF613D Kingdom and its Cities
题目意思
戳这里
S
o
l
\mathrm{Sol}
Sol
- 这道题目的重点还是建虚树,如果不会建立虚树,虚树构建学习
- 然后我们就开始愉快地树形
D
P
DP
DP了
- 设
f
u
f_u
fu表示以
u
u
u为根节点最少选择点数
- 设
g
u
g_u
gu表示以
u
u
u为根节点还没有处理地特殊点数量
- 对于转移:
- 如果这个点
u
u
u不是特殊点且
g
u
>
1
g_u>1
gu>1,那么就必须选。
- 如果这个点
u
u
u是特殊点,那么
f
u
=
(
f
u
+
g
u
)
,
g
u
=
1
f_u=(f_u+g_u),g_u=1
fu=(fu+gu),gu=1,其中
g
u
=
1
g_u=1
gu=1因为还有根节点是特殊点。
- 对于其他就是:
f
u
=
∑
f
v
,
g
u
=
∑
g
v
f_u=\sum f_v,g_u=\sum g_v
fu=∑fv,gu=∑gv
- 对于那些虚树上的点,如果
u
u
u以及
f
a
u
fa_u
fau都为特殊点,那么输出
−
1
-1
−1就可以了。
C
o
d
e
\mathrm{Code}
Code
#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int sum=0,ff=1; char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') ff=-1;
ch=getchar();
}
while(isdigit(ch))
sum=sum*10+(ch^48),ch=getchar();
return sum*ff;
}
const int N=4e5+5;
int n,m,cnt,head[N],siz[N],stak[N];
int ans,in[N],out[N],is[N],p[N],tim;
int dep[N],son[N],top[N],f[N],g[N],h[N];
struct nood
{
int nex,to;
};
nood e[N*2];
inline void jia(int u,int v)
{
e[++cnt].nex=head[u];
head[u]=cnt;
e[cnt].to=v;
}
inline void dfs(int u,int fa)
{
dep[u]=dep[fa]+1;
in[u]=++tim;
f[u]=fa;
siz[u]=1;
for ( int i=head[u];i;i=e[i].nex )
{
int v=e[i].to;
if(v==fa) continue;
dfs(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
out[u]=tim;
}
inline void dfs2(int u,int tp)
{
top[u]=tp;
if(son[u]) dfs2(son[u],tp);
for ( int i=head[u];i;i=e[i].nex )
{
int v=e[i].to;
if(v==f[u]||v==son[u]) continue;
dfs2(v,v);
}
}
inline int LCA(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=f[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
return x;
}
inline void dp(int u)
{
for ( int i=head[u];i;i=e[i].nex )
{
int v=e[i].to;
dp(v);
h[u]+=h[v];
g[u]+=g[v];
}
if(is[u]) h[u]+=g[u],g[u]=1;
else h[u]+=(g[u]>1),g[u]=(g[u]==1);
}
inline int calc(int x,int gs)
{
for ( int i=1;i<=gs;i++ )
if(is[p[i]]&&is[f[p[i]]]) return -1;
dp(x);
return h[x];
}
inline bool cmp(int x,int y)
{
return in[x]<in[y];
}
int main()
{
n=read();
for ( int i=1;i<n;i++ )
{
int u,v;
u=read(),v=read();
jia(u,v);
jia(v,u);
}
dfs(1,0);
dfs2(1,1);
memset(head,0,sizeof(head));
cnt=0;
int Q=read();
for (;Q--;)
{
int gs=read();
for ( int i=1;i<=gs;i++ )
is[(p[i]=read())]=1;
sort(p+1,p+gs+1,cmp);
for ( int i=gs;i>1;i-- )
p[++gs]=LCA(p[i],p[i-1]);
sort(p+1,p+gs+1,cmp);
gs=unique(p+1,p+gs+1)-p-1;
cnt=0;
for ( int i=1,top=0;i<=gs;i++ )
{
while(top&&out[stak[top]]<in[p[i]]) top--;
jia(stak[top],p[i]);
stak[++top]=p[i];
}
printf("%d\n",calc(p[1],gs));
for ( int i=1;i<=gs;i++ )
head[p[i]]=0,
is[p[i]]=0,
h[p[i]]=0,
g[p[i]]=0;
}
return 0;
}