洛谷 P3267 - [JLOI2016/SHOI2016]侦察守卫(树形 dp)
经典题一道,下次就称这种”覆盖距离不超过 xxx 的树形 dp“为《侦察守卫模型》
我们考虑树形 \(dp\),设 \(f_{x,j}\) 表示钦定了 \(x\) 子树内的点选/不选的状态,且 \(x\) 子树内必须要被覆盖的点都被覆盖,\(x\) 的 \(1\sim j\) 级祖先都被覆盖了的最小代价,再设 \(g_{x,j}\) 表示 \(x\) 子树内距离 \(x\ge j\) 的必须要被覆盖的点都被覆盖,而 \(x\) 子树内距离 \(x\) \(<j\) 的点及 \(x\) 的祖先的覆盖状态不做要求的最小代价。根据 \(f,g\) 的定义容易发现:
- \(\forall i,j,g_{x,i}\le f_{x,j}\),(证明?显然!)
- \(g_{x,0}=f_{x,0}\)(证明?显然!)
接下来考虑如何转移,假设我们往 \(u\) 子树内加入一个 \(v\) 子树,那么有:
- \(f_{u,i}=\min(f_{u,i}+g_{v,i},g_{u,i+1}+f_{v,i+1})\)
- \(g_{u,i}=g_{u,i}+g_{v,i-1}\)
- \(g_{u,0}=f_{u,0}\)
稍微解释一下上面三个式子,首先第三个式子根据 \(dp\) 数组的定义即可明白。\(f\) 的转移中,\(\min\) 里面第一个表示 \(u\) 本来就可以向上覆盖的情况,由于 \(u\) 可以向上覆盖 \(i\) 的距离,自然也可以向下覆盖 \(i\) 的距离,此时只要 \(v\) 子树内距离 \(v\) \(\ge i\) 的点都被覆盖了就符合要求,故代价为 \(f_{u,i}+g_{v,i}\),后面的 \(g_{u,i+1}+f_{v,i+1}\) 也是同样的道理,只不过这里 \(u\) 要向上覆盖 \(i\),\(v\) 就必须要向上覆盖 \(i+1\)。有人可能会问,两个 \(f\) 加在一起的转移到哪里去了?被你吃了?不难发现,根据 \(\forall i,j,g_{x,i}\le f_{x,j}\),两个 \(f\) 的转移肯定不如一 \(f\) 一 \(g\) 来得优,因此我们肯定不会两个 \(f\) 加在一起。而 \(g\) 的转移就相对来说比较容易了,只要 \(v\) 子树内距离 \(v\) \(\ge i\) 的点都被覆盖了就符合”\(u\) 子树内距离 \(u\) \(\ge i\) 的点都被覆盖“的要求。
同时,根据 \(f,g\) 的定义,还有:
- \(f_{u,i}=\min(f_{u,i},f_{u,i-1})\)
- \(g_{u,i}=\min(g_{u,i},g_{u,i+1})\)
这样我们就成功地处理了转移有关的问题。
最后就是 DFS 到某个点时 DP 数组的初始值,首先 \(f_{x,i}=w_x(i\in[1,D])\),因为当你只有一个点时,只有放置侦察守卫才能向上覆盖,而如果 \(x\) 是 B 神可能出现的位置,那么有 \(f_{x,0}=g_{x,0}=w_x\),否则 \(f_{x,0}=g_{x,0}=0\),因为如果 B 神不可能出现在 \(x\),那么 \(x\) 不一定要被覆盖。
时间复杂度 \(\Theta(nD)\)。
貌似这题和 CF1517F 很像?要是我早半年做到这道题说不定我那场就能一下涨上 2500 了(bushi
const int MAXN=5e5;
const int MAXD=20;
const int INF=0x3f3f3f3f;
int n,d,w[MAXN+5],hd[MAXN+5],to[MAXN*2+5],nxt[MAXN*2+5],ec=0,vis[MAXN+5];
void adde(int u,int v){to[++ec]=v;nxt[ec]=hd[u];hd[u]=ec;}
int f[MAXN+5][MAXD+2],g[MAXN+5][MAXD+2];
void dfs(int x,int fa){
for(int i=1;i<=d;i++) f[x][i]=w[x];f[x][d+1]=INF;
if(vis[x]) f[x][0]=g[x][0]=w[x];
for(int e=hd[x];e;e=nxt[e]){
int y=to[e];if(y==fa) continue;dfs(y,x);
for(int i=d;~i;i--) f[x][i]=min(f[x][i]+g[y][i],g[x][i+1]+f[y][i+1]);
for(int i=d;~i;i--) f[x][i]=min(f[x][i],f[x][i+1]);
g[x][0]=f[x][0];
for(int i=1;i<=d;i++) g[x][i]+=g[y][i-1];
for(int i=1;i<=d;i++) chkmin(g[x][i],g[x][i-1]);
}
}
int main(){
scanf("%d%d",&n,&d);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
int m;scanf("%d",&m);while(m--){int x;scanf("%d",&x);vis[x]=1;}
for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),adde(u,v),adde(v,u);
dfs(1,0);printf("%d\n",f[1][0]);
return 0;
}
洛谷 P3267 - [JLOI2016/SHOI2016]侦察守卫(树形 dp)的更多相关文章
- 洛谷 P3267 [JLOI2016/SHOI2016]侦察守卫(树形dp)
题面 luogu 题解 树形\(dp\) \(f[x][y]表示x的y层以下的所有点都已经覆盖完,还需要覆盖上面的y层的最小代价.\) \(g[x][y]表示x子树中所有点都已经覆盖完,并且x还能向上 ...
- 洛谷 P3177 [HAOI2015]树上染色 树形DP
洛谷 P3177 [HAOI2015]树上染色 树形DP 题目描述 有一棵点数为 \(n\) 的树,树边有边权.给你一个在 \(0 \sim n\)之内的正整数 \(k\) ,你要在这棵树中选择 \( ...
- 洛谷P1040 加分二叉树(树形dp)
加分二叉树 时间限制: 1 Sec 内存限制: 125 MB提交: 11 解决: 7 题目描述 设一个n个节点的二叉树tree的中序遍历为(l,2,3,...,n),其中数字1,2,3,...,n ...
- 洛谷P4438 道路 [HNOI/AHOI2018] 树形dp
正解:树形dp 解题报告: 传送门! 昂首先看懂题目趴QwQ大概就是说有棵满二叉树,有n个叶子节点(乡村)和n-1个非叶子节点,然后这棵树的每个节点有三个属性abc,对每个非叶子节点可以从与子节点的两 ...
- 洛谷 P4201 设计路线 [NOI2008] 树形dp
正解:树形dp 解题报告: 大概是第一道NOI的题目?有点激动嘻嘻 然后先放个传送门 先大概港下这题的题意是啥qwq 大概就是给一棵树,然后可以选若干条链把链上的所有边的边权变成0,但是这些链不能有交 ...
- P3267 [JLOI2016/SHOI2016]侦察守卫
$ \color{#0066ff}{ 题目描述 }$ 小R和B神正在玩一款游戏.这款游戏的地图由N个点和N-1条无向边组成,每条无向边连接两个点,且地图是连通的.换句话说,游戏的地图是一棵有N个节点的 ...
- 洛谷P1351 联合权值(树形dp)
题意 题目链接 Sol 一道很简单的树形dp,然而被我写的这么长 分别记录下距离为\(1/2\)的点数,权值和,最大值.以及相邻儿子之间的贡献. 树形dp一波.. #include<bits/s ...
- 洛谷P4099 [HEOI2013]SAO(树形dp)
传送门 HEOI的题好珂怕啊(各种意义上) 然后考虑树形dp,以大于为例 设$f[i][j]$表示$i$这个节点在子树中排名第$j$位时的总方案数(因为实际只与相对大小有关,与实际数值无关) 我们考虑 ...
- 洛谷 P1351 联合权值 —— 树形DP
题目:https://www.luogu.org/problemnew/show/P1351 树形DP,别忘了子树之间的情况(拐一下距离为2). 代码如下: #include<iostream& ...
随机推荐
- 「软件测试实战教程系列(三)」弃繁就简,接口测试神器Postman|收藏版
软件测试实战教程系列(三)弃繁就简,接口测试神器Postman|收藏版 Postman主要帮我们干了三件事: 1.把相关集合放到一个集合当中方便管理. 2.对指定接口发送请求. 3.断言 下面我们使用 ...
- 【c++ Prime 学习笔记】第1章 开始
1.1 编写一个简单的程序 int main() { return 0; } 函数 包含4部分: 返回类型(return type) 函数名(function name) 形参列表(parameter ...
- vue3.x移动端适配px2rem
1.什么是px2rem px2rem是一个插件能将px自动转换为rem,以适配各种不同的屏幕尺寸.前端开发可以直接使用设计稿量出的尺寸或者蓝湖给出的px进行布局,这样极大的提高了开发效率. 2.前提条 ...
- Java:NIO 学习笔记-2
Java:NIO 学习笔记-2 上一篇 NIO 学习笔记-1 看了 尚硅谷 的相应教程,此处又对比看了 黑马程序员 的课程 JAVA通信架构I/O模式,做了相应的笔记 前言 在 Java 的软件设计开 ...
- Git浅析
Git浅析 索引 Git的常用命令 GitHub的使用 Git版本创建和回退 Git的工作区和暂存区 Git分支管理 1-Git的常用命令 01.创建一个版本库--进入相应的目录 git init 可 ...
- BUAA软件工程个人作业-软件案例分析
BUAA个人博客作业-软件案例分析 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 软件案例分析 我在这个课程的目标是 学习开发软件的能力 这个作 ...
- spring cache整合redis
在项目中,我们经常需要将一些常用的数据使用缓存起来,避免频繁的查询数据库造成效率低下.spring 为我们提供了一套基于注解的缓存实现,方便我们实际的开发.我们可以扩展spring的cache接口以达 ...
- 零基础入门非常好的C语言基础资料
C语言程序的结构认识 用一个简单的c程序例子,介绍c语言的基本构成.格式.以及良好的书写风格,使小伙伴对c语言有个初步认识. 例1:计算两个整数之和的c程序: #include main() { in ...
- 架构师之路-redis集群解析
引子 上篇<架构师之路-https底层原理>里我提到了上面的整体视图,文章也介绍了想要真正能在工作中及时正确解决问题的基本功:原理理解透彻.今天以redis集群解析为例介绍一个及时敏锐的发 ...
- 嵌入式开发板nfs挂载
板子要开始调试了,第一个头大的问题就是调试过程中更新的文件怎么更新到板子上,以前用sd卡拷贝来来回回太浪费时间了,adb也需要接线各种连接操作. 现在板子有wifi可用,是时候把nfs共享搭起来了. ...