考虑树形\(DP\),设\(num_x\)记录的为当\(1\)为根时,以\(x\)为子树中重要城市的个数。

那么进行分类讨论:

① 当\(num_x≠0\)时,则需将其所有满足\(num_y≠0\)的儿子\(y\)删去。

② 当\(num_x=0\)时,若满足\(num_y≠0\)的儿子\(y\)个数\(cnt=1\),则直接让\(num\)进行向上传递,若满足\(num_y≠0\)的儿子\(y\)个数\(cnt>1\),则需删去\(x\)本身。

不合法的情况特判掉。

考虑到多次询问和树上点集的特性,考虑用虚树来优化\(DP\)。

多次建虚树时记得清空\(num\),但不要用\(memset\),无法保证复杂度,应记录虚树上的点,只清零这些点。

其他实现细节就看代码吧。

\(code:\)

#include<bits/stdc++.h>
#define maxn 200010
using namespace std;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag) x=-x;
}
int n,q,ans,tmp_cnt;
bool flag;
int query[maxn],tmp[maxn],num[maxn];
struct edge
{
int to,nxt;
}e[maxn];
int head[maxn],edge_cnt;
void add(int from,int to)
{
e[++edge_cnt]=(edge){to,head[from]};
head[from]=edge_cnt;
}
int dfn_cnt;
int de[maxn],dfn[maxn],top_fa[maxn],fa[maxn],son[maxn],siz[maxn];
void dfs_son(int x,int fath)
{
siz[x]=1;
fa[x]=fath;
de[x]=de[fath]+1;
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(y==fath) continue;
dfs_son(y,x);
siz[x]+=siz[y];
if(siz[son[x]]<siz[y]) son[x]=y;
}
}
void dfs_chain(int x,int tp)
{
dfn[x]=++dfn_cnt,top_fa[x]=tp;
if(son[x]) dfs_chain(son[x],tp);
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(dfn[y]) continue;
dfs_chain(y,y);
}
}
int lca(int x,int y)
{
while(top_fa[x]!=top_fa[y])
{
if(de[top_fa[x]]<de[top_fa[y]]) swap(x,y);
x=fa[top_fa[x]];
}
if(dfn[x]>dfn[y]) swap(x,y);
return x;
}
bool cmp(const int &a,const int &b)
{
return dfn[a]<dfn[b];
}
int st[maxn],top;
void insert(int x)
{
if(x==1) return;
if(top==1)
{
st[++top]=x;
return;
}
int anc=lca(x,st[top]);
if(anc==st[top])
{
st[++top]=x;
return;
}
while(top>1&&dfn[anc]<=dfn[st[top-1]]) add(st[top-1],st[top]),top--,tmp[++tmp_cnt]=st[top];
if(anc!=st[top]) add(anc,st[top]),st[top]=anc,tmp[++tmp_cnt]=st[top];
st[++top]=x;
}
void dp(int x)
{
int cnt=0,sum=0;
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
dp(y);
if(num[x]&&num[y]) ans++;
if(!num[x]&&num[y])
{
cnt++;
sum+=num[y];
}
}
if(!num[x])
{
if(cnt==1) num[x]+=sum;
if(cnt>1) ans++;
}
head[x]=0;
}
void clear()
{
edge_cnt=0;
memset(head,0,sizeof(head));
}
int main()
{
read(n);
for(int i=1;i<n;++i)
{
int a,b;
read(a),read(b);
add(a,b),add(b,a);
}
dfs_son(1,0);
dfs_chain(1,1);
clear();
read(q);
while(q--)
{
int k;
read(k);
edge_cnt=tmp_cnt=flag=ans=0;
for(int i=1;i<=k;++i)
{
read(query[i]);
num[query[i]]++;
}
for(int i=1;i<=k;++i)
{
if(num[fa[query[i]]])
{
puts("-1");
flag=true;
break;
}
}
if(flag)
{
for(int i=1;i<=k;++i) num[query[i]]=0;
continue;
}
sort(query+1,query+k+1,cmp);
st[top=1]=1,tmp[tmp_cnt=1]=1;
for(int i=1;i<=k;++i) insert(query[i]);
while(top) add(st[top-1],st[top]),top--,tmp[++tmp_cnt]=st[top];
dp(1);
for(int i=1;i<=tmp_cnt;++i) num[tmp[i]]=0;
for(int i=1;i<=k;++i) num[query[i]]=0;
printf("%d\n",ans);
}
return 0;
}

题解 CF613D 【Kingdom and its Cities】的更多相关文章

  1. CF613D Kingdom and its Cities 虚树 树形dp 贪心

    LINK:Kingdom and its Cities 发现是一个树上关键点问题 所以考虑虚树刚好也有标志\(\sum k\leq 100000\)即关键点总数的限制. 首先当k==1时 答案显然为0 ...

  2. CF613D Kingdom and its Cities 虚树

    传送门 $\sum k \leq 100000$虚树套路题 设$f_{i,0/1}$表示处理完$i$以及其所在子树的问题,且处理完后$i$所在子树内是否存在$1$个关键点满足它到$i$的路径上不存在任 ...

  3. CF613D:Kingdom and its Cities(树形DP,虚树)

    Description 一个王国有n座城市,城市之间由n-1条道路相连,形成一个树结构,国王决定将一些城市设为重要城市. 这个国家有的时候会遭受外敌入侵,重要城市由于加强了防护,一定不会被占领.而非重 ...

  4. [CF613D]Kingdom and its Cities

    description 题面 data range \[n, q,\sum k\le 10^5\] solution 还是虚树的练手题 \(f[0/1][u]\)表示\(u\)的子树内,\(u\)是否 ...

  5. CF613D Kingdom and its Cities 虚树 + 树形DP

    Code: #include<bits/stdc++.h> #define ll long long #define maxn 300003 #define RG register usi ...

  6. CF613D Kingdom and its Cities(虚树+贪心)

    很休闲的一个题啊 其实一看到关于\(\sum k\)的限制,就知道是个虚树的题了 首先我们把虚树建出来,然后考虑怎么计算个数呢? 我们令\(f[x]\)表示以\(x\)的子树中,剩余了多少个还没有切断 ...

  7. 【CF613D】Kingdom and its Cities 虚树+树形DP

    [CF613D]Kingdom and its Cities 题意:给你一棵树,每次询问给出k个关键点,问做多干掉多少个非关键点才能使得所有关键点两两不连通. $n,\sum k\le 10^5$ 题 ...

  8. 【CF613D】Kingdom and its Cities

    [CF613D]Kingdom and its Cities 题面 洛谷 题解 看到关键点当然是建虚树啦. 设\(f[x]\)表示以\(x\)为根的子树的答案,\(g[x]\)表示以\(x\)为根的子 ...

  9. 【CF613D】Kingdom and its Cities(虚树,动态规划)

    [CF613D]Kingdom and its Cities(虚树,动态规划) 题面 洛谷 CF 翻译洛谷上有啦 题解 每次构建虚树,首先特判无解,也就是关键点中存在父子关系. 考虑\(dp\),设\ ...

随机推荐

  1. windows 64位上安装mysql 5.7版本

    下载的mysql不是安装exe的软件,而是在windows上编译好的二进制mysql软件 下载安装之后配置环境变量:将目录D:\Program Files\mysql-5.7.18-winx64\my ...

  2. Python3-hashlib模块-加密算法之安全哈希

    Python3中的hashlib模块提供了多个不同的安全哈希算法的通用接口 hashlib模块代替了Python2中的md5和sham模块,使用这个模块一般分为3步 1.创建一个哈希对象,使用哈希算法 ...

  3. Django实现图片上传并前端页面显示

    Django实现图片上传和图片显示 开始之前我们先确认环境中已经安装了Pillow,如果没有安装,可以通过pip install Pillow来安装,这个是python的图像处理库 数据库设置 我们创 ...

  4. 基于Docker Compose的.NET Core微服务持续发布

    是不是现在每个团队都需要上K8s才够潮流,不用K8s是不是就落伍了.今天,我就通过这篇文章来回答一下. 一.先给出我的看法和建议 我想说的是,对于很多的微小团队来说,可能都不是一定要上K8s,毕竟上K ...

  5. 入门大数据---通过Flume、Sqoop分析日志

    一.Flume安装 参考:Flume 简介及基本使用 二.Sqoop安装 参考:Sqoop简介与安装 三.Flume和Sqoop结合使用案例 日志分析系统整体架构图: 3.1配置nginx环境 请参考 ...

  6. 源码剖析@contextlib.contextmanager

    示例 @contextlib.contextmanager def result(a): print('before') yield print('after') 外层装饰源码 包装func函数,真实 ...

  7. [CEOI1999]Parity Game 题解

    P5937 [CEOI1999]Parity Game 洛谷P5937 P5937 [CEOI1999]Parity Game 前言: 个人感觉这道题初看想不到并查集啊!(说实话我题都没读懂,第二遍才 ...

  8. 泛型<T>,是你肿莫了,还是我错了...

    委托自定义数组排序 项目一共三个文件如下. CSort.cs using System; using System.Collections.Generic; using System.Linq; us ...

  9. Apache DolphinScheduler(海豚调度) - 1.3 系列核心表结构剖析

    Apache DolphinScheduler 是一个分布式去中心化,易扩展的可视化 DAG 工作流任务调度系统.致力于解决数据处理流程中错综复杂的依赖关系,使调度系统在数据处理流程中开箱即用. 近日 ...

  10. 不花钱搞定PDF编辑难题

    PDF格式是专为显示而设计的格式,并不容易被编辑,市面上并没有一款可以真正免费使用的PDF编辑器. 不花钱搞定PDF编辑难题的办法: 1.免费使用PDF编辑器+去水印:免费版的PDF编辑器不是会加水印 ...