P3267 [JLOI2016/SHOI2016]侦察守卫
$ \color{#0066ff}{ 题目描述 }$
小R和B神正在玩一款游戏。这款游戏的地图由N个点和N-1条无向边组成,每条无向边连接两个点,且地图是连通的。换句话说,游戏的地图是一棵有N个节点的树。
游戏中有一种道具叫做侦查守卫,当一名玩家在一个点上放置侦查守卫后,它可以监视这个点以及与这个点的距离在D以内的所有点。这里两个点之间的距离定义为它们在树上的距离,也就是两个点之间唯一的简单路径上所经过边的条数。在一个点上放置侦查守卫需要付出一定的代价,在不同点放置守卫的代价可能不同。
现在小R知道了所有B神可能会出现的位置,请你计算监视所有这些位置的最小代价。
\(\color{#0066ff}{输入格式}\)
第一行包含两个正整数N和D,分别表示地图上的点数和侦查守卫的视野范围。约定地图上的点用1到N的整数编号。
第二行N个正整数,第i个正整数表示在编号为i的点放置侦查守卫的代价Wi。保证Wi<=1000。
第三行一个正整数M,表示B神可能出现的点的数量。保证M<=N。
第四行M个正整数,分别表示每个B神可能出现的点的编号,从小到大不重复地给出。
接下来N-1行,每行包含两个正整数U,V,表示在编号为U的点和编号为V的点之间有一条无向边。
\(\color{#0066ff}{输出格式}\)
仅一行一个整数,表示监视所有B神可能出现的点所需要的最小代价
\(\color{#0066ff}{输入样例}\)
12 2
8 9 12 6 1 1 5 1 4 8 10 6
10
1 2 3 5 6 7 8 9 10 11
1 3
2 3
3 4
4 5
4 6
4 7
7 8
8 9
9 10
10 11
11 12
\(\color{#0066ff}{输出样例}\)
10
\(\color{#0066ff}{数据范围与提示}\)
对于所有的数据,N<=500000,D<=20
\(\color{#0066ff}{题解}\)
对于这种在树上覆盖的问题,是一个比较经典的树形DP模型
状态\(f[i][j]\)表示以i为根子树从i向下有j层未覆盖的最小代价,j可以为负数,如果是负数,就是子树全覆盖,并向外覆盖一些层
所以我们再开一个\(g[i][j]\)表示以i为根子树全覆盖,并且向外覆盖了j层的方案数
首先,对于必覆盖点,初始化就是\(f[i][0]=g[i][0]=val[i]\)
注意当\(j\ge 1\)时,f覆盖的范围是不包括当前点的(j层未覆盖),但是g包括了(i向外j全覆盖)
所以\(g[i][j]\)也要初始化一下
考虑转移
对于f,显然有\(f[x][j] = min\{f[x][j-1]\}\)
还有就是子树统计\(f[x][j]+=f[y][j-1]\)
对于g,显然有\(g[x][i]=min\{g[x][i+1]\}\)
还有,就是考虑x的外面由哪个子树覆盖,这个覆盖包括了x子树内部,\(g[y][j]\)覆盖了\(f[x][j]\)未覆盖的j层
\(g[x][j]=min\{f[x][j+1]+g[y][j+1],f[y][j]+g[x][j]\}\)
答案就是\(f[1][0]\)
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 5e5 + 100;
const int inf = 0x7fffffff;
int f[maxn][25], g[maxn][25], val[maxn];
int n, d, m;
bool vis[maxn];
struct node {
int to;
node *nxt;
node(int to = 0, node *nxt = NULL): to(to), nxt(nxt) {}
};
node *head[maxn];
void add(int from, int to) { head[from] = new node(to, head[from]); }
void dfs(int x, int fa) {
if(vis[x]) f[x][0] = g[x][0] = val[x];
for(int i = 1; i <= d; i++) g[x][i] = val[x];
g[x][d + 1] = inf;
for(node *i = head[x]; i; i = i->nxt) {
if(i->to == fa) continue;
dfs(i->to, x);
for(int j = 0; j <= d; j++) g[x][j] = std::min(g[x][j] + f[i->to][j], g[i->to][j + 1] + f[x][j + 1]);
for(int j = d - 1; j >= 0; j--) g[x][j] = std::min(g[x][j], g[x][j + 1]);
f[x][0] = g[x][0];
for(int j = 1; j <= d; j++) f[x][j] += f[i->to][j - 1];
for(int j = 1; j <= d; j++) f[x][j] = std::min(f[x][j], f[x][j - 1]);
}
}
int main() {
n = in(), d = in();
for(int i = 1; i <= n; i++) val[i] = in();
m = in();
for(int i = 1; i <= m; i++) vis[in()] = true;
int x, y;
for(int i = 1; i < n; i++) x = in(), y = in(), add(x, y), add(y, x);
dfs(1, 0);
printf("%d\n", f[1][0]);
return 0;
}
P3267 [JLOI2016/SHOI2016]侦察守卫的更多相关文章
- 洛谷 P3267 - [JLOI2016/SHOI2016]侦察守卫(树形 dp)
洛谷题面传送门 经典题一道,下次就称这种"覆盖距离不超过 xxx 的树形 dp"为<侦察守卫模型> 我们考虑树形 \(dp\),设 \(f_{x,j}\) 表示钦定了 ...
- 洛谷 P3267 [JLOI2016/SHOI2016]侦察守卫(树形dp)
题面 luogu 题解 树形\(dp\) \(f[x][y]表示x的y层以下的所有点都已经覆盖完,还需要覆盖上面的y层的最小代价.\) \(g[x][y]表示x子树中所有点都已经覆盖完,并且x还能向上 ...
- [JLOI2016/SHOI2016]侦察守卫(树形dp)
小R和B神正在玩一款游戏.这款游戏的地图由N个点和N-1条无向边组成,每条无向边连接两个点,且地图是连通的.换句话说,游戏的地图是一棵有N个节点的树. 游戏中有一种道具叫做侦查守卫,当一名玩家在一个点 ...
- [JLOI2016/SHOI2016]侦察守卫
嘟嘟嘟 这道题可以说是[HNOI2003]消防局的设立的升级版.距离从2改为了d. 辛亏d只有20,这也就是一个切入点. 令f[u][j]表示u四周 j - 1的距离需要被覆盖,g[u][j]表示u可 ...
- BZOJ4557:[JLOI2016/SHOI2016]侦察守卫——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=4557 小R和B神正在玩一款游戏.这款游戏的地图由N个点和N-1条无向边组成,每条无向边连接两个点, ...
- Luogu 3267 [JLOI2016/SHOI2016]侦察守卫
以后要记得复习鸭 BZOJ 4557 大佬的博客 状态十分好想,设$f_{x, i}$表示以覆盖完$x$为根的子树后还能向上覆盖$i$层的最小代价,$g_{x, i}$表示以$x$为根的子树下深度为$ ...
- Luogu3267 [JLOI2016/SHOI2016]侦察守卫 (树形DP)
树形DP,一脸蒙蔽.看了题解才发现它转移状态与方程真不愧神题! \(f[x][y]\)表示\(x\)的\(y\)层以下的所有点都已经覆盖完,还需要覆盖上面的\(y\)层的最小代价. \(g[x][y] ...
- DP学习记录Ⅰ
DP学习记录Ⅱ 前言 状态定义,转移方程,边界处理,这三部分想好了,就问题不大了.重点在状态定义,转移方程是基于状态定义的,边界处理是方便转移方程的开始的.因此最好先在纸上写出自己状态的意义,越详细越 ...
- bzoj 4557: [JLoi2016]侦察守卫 树归
bzoj 4557: [JLoi2016]侦察守卫 设f[x][j]表示覆盖以x为根的子树的所有应该被覆盖的节点,并且以x为根的子树向下j层全部被覆盖的最小代价. 设g[x][j]表示与x距离大于j全 ...
随机推荐
- Java核心技术-接口、lambda表达式与内部类
本章将主要介绍: 接口技术:主要用来描述类具有什么功能,而并不给出每个功能的具体实现.一个类可以实现一个或多个接口. lambda表达式:这是一种表示可以在将来的某个时间点执行的代码块的简洁方法. 内 ...
- linux系统如何安装vmware Tools(下面以CentOS为例)
VMwareTools是VMware虚拟机中很重要的一个工具包,有些时候在虚拟机中安装完操作系统会缺少网卡驱动,不能上网,这时只要安装VMwareTools就可以解决问题,下面以CentOS为例,来说 ...
- [Training Video - 6] [File Reading] [Java] Create and Write Excel File Using Apache POI API
package com.file.properties; import java.io.File; import java.io.FileNotFoundException; import java. ...
- mysql 空间索引的使用
CREATE TABLE tb_geo(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(128) NOT NULL,pnt POINT NOT NULL, ...
- SVN客户端--TortoiseSVN使用说明【转】
TortoiseSVN是windows下其中一个非常优秀的SVN客户端工具.通过使用它,我们可以可视化的管理我们的版本库.不过由于它只是一个客户端,所以它不能对版本库进行权限管理. TortoiseS ...
- 【小梅哥SOPC学习笔记】NIOS II工程目录改变时project无法编译问题
解决NIOS II工程移动在磁盘上位置后project无法编译问题 说明:本文档于2017年3月4日由小梅哥更新部分内容,主要是增加了讲解以Quartus II13.0为代表的经典版本和以15.1为代 ...
- RDD介绍与执行
repartition 增加或减少分区.会产生shuffle.(多个分区分到一个分区不会产生shuffle) coalesce coalesce常用来减少分区,第二个参数是减少分区的过程中是否产生sh ...
- Java多线程设计模式(三)
目录(?)[-] Read-Wirte Lock Pattern Thread-Per-Message Pattern Worker Thread Pattern Read-Wirte Lock ...
- 6、Semantic-UI之动画按钮样式
6.1 动画按钮样式 在Semantic-UI中提供了三种动画样按钮式表,分别为: 左右移动 上下移动 淡入淡出 在实际开发中,很少使用这种动画按钮,根据实际情况使用,强制使用到页面中反而不太适合 ...
- maven-multiModule
主pom的定义 packaging:pom modules的指定 dependencyManagement的指定 properties的指定 build或profile的设置 子module的创建 在 ...