CF613D
题意:
一个王国有n座城市,城市之间由n-1条道路相连,形成一个树结构,国王决定将一些城市设为重要城市。
这个国家有的时候会遭受外敌入侵,重要城市由于加强了防护,一定不会被占领。而非重要城市一旦被占领,这座城市就不能通行。
国王定了若干选择重要城市的计划,他想知道,对于每个计划,外敌至少要占领多少个非重要城市,才会导致重要城市之间两两不连通。如果外敌无论如何都不可能导致这种局面,输出-1
————————————————————————————————————————
首先,在洛谷交的,有一个点没有过。CF,外语网站而且很慢,不试了!
建立虚树,然后在虚树上面树形DP。
虚树,就是在做树形DP时,我们经常发现有许多点根本没用,比如这个题目中的非重要城市。我们可以把重要节点和他们的连接点(LCA)取出来重新建一棵树,这就是虚树。
方法:
首先,dfs,求出dfs序:DFN,并求出每个点的深度dep[]和LCA辅助数组f[][]
void dfs(int u,int fa)
{
f[u][0]=fa;
for(int i=1;i<20 && f[u][i-1]!=0;++i)f[u][i]=f[f[u][i-1]][i-1];
dfn[u]=++tim;dep[u]=dep[fa]+1;
for(int i=head[u];i;i=e[i].nxt)
if(e[i].v!=fa)dfs(e[i].v,u);
}
然后,对于所有的重要节点进行记录(pt[])并打标记(ispt[])
下面,将重要节点(pt[])按照DFN[]进行排序
最后,我们将pt[]中的重要节点一次取出建立虚树。
建立的虚树采用增量的方法:
把取出的点一次加入到栈里面,从栈底到栈顶的重要节点可以连成一条从根方向到叶子方向的链。
当加入当前点u时,如果栈中没用其它的点则可以直接加入点u
如果u点与栈顶的点的lca是栈顶点,则可以直接将u点加入,这样栈中的点形成一条更长的链
如果栈顶点和u点的lca不是栈顶点,那么也就是u点和栈顶点处于原树中不同的分支。我们比lca更深(比较dep[])的点依次弹出,并把相邻的点建边(这就是虚树的一部分)。然后把判断lca是否在栈中,如果不在就需要把lca加入栈中,然后把u点加入栈中。
这样所有的点都加入完成后,最后还剩余了栈中的一条链,把栈中的点一次出栈并建边,虚树完成。
注:为了有一个总的根,所以通常把1号点加入栈中。
void insert(int x)
{
if(top==0)
{
sta[top=1]=x;
return;
}
int l=lca(x,sta[top]);
if(l==sta[top])
{
sta[++top]=x;
return;
}
while(top>1 && dep[sta[top-1]]>=dep[l])
{
addage(sta[top],sta[top-1],ee,headd,jss);
addage(sta[top-1],sta[top],ee,headd,jss);
--top;
}
if(l!=sta[top])
{
addage(sta[top],l,ee,headd,jss);
addage(l,sta[top],ee,headd,jss);
sta[top]=l;
}
sta[++top]=x;
}
void build()
{
jss=0;
memset(headd,0,sizeof headd);
if(pt[1]!=1)sta[top=1]=1;
for(int i=1;i<=m;++i)
insert(pt[i]);
while(top>1)
{
addage(sta[top],sta[top-1],ee,headd,jss);
addage(sta[top-1],sta[top],ee,headd,jss);
--top;
}
}
————————————————————————————————————————

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=1e5+10;
4 int n,q;
5 struct edge
6 {
7 int u,v,nxt;
8 }e[maxn],ee[maxn];
9 int head[maxn],headd[maxn],js,jss;
10 void addage(int u,int v,edge e[],int head[],int &js)
11 {
12 e[++js].u=u;e[js].v=v;
13 e[js].nxt=head[u];head[u]=js;
14 }
15 int dfn[maxn],tim,f[maxn][20],dep[maxn];
16 void dfs(int u,int fa)
17 {
18 f[u][0]=fa;
19 for(int i=1;i<20 && f[u][i-1]!=0;++i)f[u][i]=f[f[u][i-1]][i-1];
20 dfn[u]=++tim;dep[u]=dep[fa]+1;
21 for(int i=head[u];i;i=e[i].nxt)
22 if(e[i].v!=fa)dfs(e[i].v,u);
23 }
24 int pt[maxn],m,sta[maxn],top;
25 bool ispt[maxn];
26 bool cmp(int a,int b)
27 {
28 return dfn[a]<dfn[b];
29 }
30 int lca(int u,int v)
31 {
32 if(dep[v]>dep[u])swap(u,v);
33 for(int i=19;i>=0;--i)
34 if(dep[f[u][i]]>=dep[v])u=f[u][i];
35 if(u==v)return u;
36 for(int i=19;i>=0;--i)
37 if(f[u][i]!=f[v][i])u=f[u][i],v=f[v][i];
38 return f[u][0];
39 }
40 void insert(int x)
41 {
42 if(top==0)
43 {
44 sta[top=1]=x;
45 return;
46 }
47 int l=lca(x,sta[top]);
48 if(l==sta[top])
49 {
50 sta[++top]=x;
51 return;
52 }
53 while(top>1 && dep[sta[top-1]]>=dep[l])
54 {
55 addage(sta[top],sta[top-1],ee,headd,jss);
56 addage(sta[top-1],sta[top],ee,headd,jss);
57 --top;
58 }
59 if(l!=sta[top])
60 {
61 addage(sta[top],l,ee,headd,jss);
62 addage(l,sta[top],ee,headd,jss);
63 sta[top]=l;
64 }
65 sta[++top]=x;
66 }
67 void build()
68 {
69 jss=0;
70 memset(headd,0,sizeof headd);
71 if(pt[1]!=1)sta[top=1]=1;
72 for(int i=1;i<=m;++i)
73 insert(pt[i]);
74 while(top>1)
75 {
76 addage(sta[top],sta[top-1],ee,headd,jss);
77 addage(sta[top-1],sta[top],ee,headd,jss);
78 --top;
79 }
80 }
81 int ff[maxn],g[maxn];
82 void dp(int u,int fa)
83 {
84 ff[u]=g[u]=0;
85 for(int i=head[u];i;i=e[i].nxt)
86 {
87 int v=e[i].v;
88 if(v==fa)continue;
89 dp(v,u);
90 ff[u]+=ff[v];g[u]+=g[v];
91 }
92 if(!ispt[u])
93 {
94 ff[u]+=(g[u]>1);
95 g[u]=(g[u]==1);
96 }
97 else
98 {
99 ff[u]+=g[u];
100 g[u]=1;
101 }
102 }
103 int main()
104 {
105 scanf("%d",&n);
106 for(int u,v,i=1;i<n;++i)
107 {
108 scanf("%d%d",&u,&v);
109 addage(u,v,e,head,js);addage(v,u,e,head,js);
110 }
111 dfs(1,0);
112 scanf("%d",&q);
113 while(q--)
114 {
115 scanf("%d",&m);
116 memset(pt,0,sizeof pt);
117 memset(ispt,0,sizeof ispt);
118 for(int i=1;i<=m;++i)
119 {
120 scanf("%d",pt+i);
121 ispt[pt[i]]=1;
122 }
123 sort(pt+1,pt+m,cmp);
124 bool flag=1;
125 for(int i=1;i<=m;++i)
126 if(ispt[f[pt[i]][0]])flag=0;
127 if(!flag)
128 {
129 puts("-1");
130 continue;
131 }
132 build();
133 dp(1,0);
134 printf("%d\n",ff[1]);
135 }
136 return 0;
137 }
CF613D的更多相关文章
- 【CF613D】Kingdom and its Cities 虚树+树形DP
[CF613D]Kingdom and its Cities 题意:给你一棵树,每次询问给出k个关键点,问做多干掉多少个非关键点才能使得所有关键点两两不连通. $n,\sum k\le 10^5$ 题 ...
- 【CF613D】Kingdom and its Cities
[CF613D]Kingdom and its Cities 题面 洛谷 题解 看到关键点当然是建虚树啦. 设\(f[x]\)表示以\(x\)为根的子树的答案,\(g[x]\)表示以\(x\)为根的子 ...
- 【CF613D】Kingdom and its Cities(虚树,动态规划)
[CF613D]Kingdom and its Cities(虚树,动态规划) 题面 洛谷 CF 翻译洛谷上有啦 题解 每次构建虚树,首先特判无解,也就是关键点中存在父子关系. 考虑\(dp\),设\ ...
- CF613D Kingdom and its Cities 虚树
传送门 $\sum k \leq 100000$虚树套路题 设$f_{i,0/1}$表示处理完$i$以及其所在子树的问题,且处理完后$i$所在子树内是否存在$1$个关键点满足它到$i$的路径上不存在任 ...
- CF613D:Kingdom and its Cities(树形DP,虚树)
Description 一个王国有n座城市,城市之间由n-1条道路相连,形成一个树结构,国王决定将一些城市设为重要城市. 这个国家有的时候会遭受外敌入侵,重要城市由于加强了防护,一定不会被占领.而非重 ...
- Kingdom and its Cities - CF613D
Meanwhile, the kingdom of K is getting ready for the marriage of the King's daughter. However, in or ...
- [CF613D]Kingdom and its Cities
description 题面 data range \[n, q,\sum k\le 10^5\] solution 还是虚树的练手题 \(f[0/1][u]\)表示\(u\)的子树内,\(u\)是否 ...
- CF613D Kingdom and its Cities 虚树 + 树形DP
Code: #include<bits/stdc++.h> #define ll long long #define maxn 300003 #define RG register usi ...
- 题解 CF613D 【Kingdom and its Cities】
考虑树形\(DP\),设\(num_x\)记录的为当\(1\)为根时,以\(x\)为子树中重要城市的个数. 那么进行分类讨论: ① 当\(num_x≠0\)时,则需将其所有满足\(num_y≠0\)的 ...
- CF613D Kingdom and its Cities 虚树 树形dp 贪心
LINK:Kingdom and its Cities 发现是一个树上关键点问题 所以考虑虚树刚好也有标志\(\sum k\leq 100000\)即关键点总数的限制. 首先当k==1时 答案显然为0 ...
随机推荐
- Could not open ServletContext resource [/WEB-INF/applicationContext.xml] 解决办法
Spring官方文档中规定,如果在上下文中没有指定contextConfigLoction配置文件的位置,则会默认去WEB-INF中去寻找对应的配置文件. 理论上classpath的默认路径是WEB- ...
- 备战金三银四!一线互联网公司java岗面试题整理:Java基础+多线程+集合+JVM合集!
前言 回首来看2020年,真的是印象中过的最快的一年了,真的是时间过的飞快,还没反应过来年就夸完了,相信大家也已经开始上班了!俗话说新年新气象,马上就要到了一年之中最重要的金三银四,之前一直有粉丝要求 ...
- 认识PHP8
PHP 团队于2020年11月26日宣布 PHP 8 正式发布!这意味着将不会有 PHP 7.5 版本.PHP8 目前正处于非常活跃的开发阶段,所以在接下来的几个月里,情况可能会发生很大的变化.我也分 ...
- mysql 创建[序列],功能类似于oracle的序列
参考自菜鸟教程 https://www.runoob.com/mysql/mysql-using-sequences.html 使用函数创建自增序列管理表(批量使用自增表,设置初始值,自增幅度) 第一 ...
- python之json、pickle模块
一.json模块 之前我们学习过用eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候, ...
- android 百度地图 团队开发及正式apk发布
百度地图开发关键是获取正确的API Key, 百度官网写的只是在你本地的机器能运行 你把AndroidManifest.xml(这里是最新的v2_4_1,API Key配置在这里) svn 提交后 ...
- WebSocket协议中文版
WebSocket协议中文版 摘要 WebSocket协议实现在受控环境中运行不受信任代码的一个客户端到一个从该代码已经选择加入通信的远程主机之间的全双工通信.用于这个安全模型是通常由web浏览器使用 ...
- Kali Debian 修改时区
1.KaliDebian默认读取时区文件是/etc/localtime(重建软连接,达到修改时区目的) 2./etc/localtime是个软连接,连接到时区文件/usr/share/zoneinfo ...
- 【C++】《C++ Primer 》第二章
第二章 变量和基本类型 指针和引用的不同点 引用不是一个对象,它没有实际地址,但是指针是一个对象.允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象. 指针无须在定义时赋初值.
- Tomcat配置上遇到的一些问题
Tomcat启动:在bin目录下双击startup.bat文件就行. 访问:在浏览器输入http://localhost:8080 回车访问的是自己 的界面: http://othersip:8080 ...