题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4557

题意概述:

  给出一棵树,每个点付出代价w[i]可以控制距离和它不超过d的点,现在给出一些点,问控制这些点的最小代价是多少。

分析:

  观察一下数据范围发现算算法的复杂度可能和d有关。横看竖看这像是一个树形dp,所以我们就把d搞到状态方程里面去嘛怎么就完全没有想到呢......

  既然要用树形dp,就要先分析一下性质。

  一个点如果被选择成为控制点,那么它可以控制的点有:子树中深度不超过d的点,祖先中和它距离不超过d的点,以及祖先的子树中的一些点。

  感觉很麻烦的样子......因为对于那些祖先子树中的点控制的方向突然向上又向下了。

  我们考虑到常用的技巧,在树形dp中,如果两个点会对答案产生贡献,我们在其LCA处统计贡献。于是我们设两个dp方程:

  f(i,x)表示i点的子树中需要被控制的点全部被控制,还可以向上控制x层的最小代价;g(i,x)表示i点的子树中x层及以下需要被控制的点全部被控制的最小代价。

  需要向上控制x层,那么儿子中就需要有点可以向上控制x +1层的点被选择,对于新来的子树j有两种情况,一个是我们需要的点在这个新的子树中,一个是我们需要的点在原来的子树中。

  f(i,x)=min(f(i,x)+g(j,x),f(j,x+1)+g(i,x+1))

  init:一开始把每点i当成孤点,那么向上控制1~d层就只有靠自己,f值初始化为w[i];f[i][0],g[i][0]根据这个点本身是否需要监视来判断。

  但是注意答案在控制的长度恰好为x的时候不一定是最优的,可能稍微控制的长度大一点答案反而更优,于是把方程的意义改一下,改成至少控制x层。

  g(i,x)=sum{g(j,x-1)|i->j},g(i,0)=f(i,0)

  小技巧:怎么维护至少这个性质?和看起来更劣的状态取min即可。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<cctype>
#define inf 1e9
using namespace std;
const int maxn=;
const int maxd=; int N,D,M,W[maxn];
struct edge{ int to,next; }E[maxn<<];
int first[maxn],np,f[maxn][maxd],g[maxn][maxd];
bool ob[maxn]; void _scanf(int &x)
{
x=;
char ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') x=x*+ch-'',ch=getchar();
}
void add_edge(int u,int v)
{
E[++np]=(edge){v,first[u]};
first[u]=np;
}
void data_in()
{
_scanf(N);_scanf(D);
for(int i=;i<=N;i++) _scanf(W[i]);
_scanf(M);
int x,y;
for(int i=;i<=M;i++){
_scanf(x); ob[x]=;
}
for(int i=;i<N;i++){
_scanf(x);_scanf(y);
add_edge(x,y); add_edge(y,x);
}
}
void DFS(int i,int fa)
{
for(int d=;d<=D;d++) f[i][d]=W[i];
f[i][D+]=inf;
if(ob[i]) f[i][]=g[i][]=W[i];
for(int p=first[i];p;p=E[p].next){
int j=E[p].to;
if(j==fa) continue;
DFS(j,i);
for(int d=;d<=D;d++)
f[i][d]=min(f[i][d]+g[j][d],f[j][d+]+g[i][d+]);
for(int d=D;d>=;d--) f[i][d]=min(f[i][d],f[i][d+]);
g[i][]=f[i][];
for(int d=;d<=D;d++) g[i][d]+=g[j][d-];
for(int d=;d<=D;d++) g[i][d]=min(g[i][d],g[i][d-]);
}
}
void work()
{
DFS(,);
printf("%d\n",f[][]);
}
int main()
{
data_in();
work();
return ;
}

BZOJ 4557 JLOI2016 侦查守卫 树形dp的更多相关文章

  1. bzoj 4557: [JLoi2016]侦察守卫【树形dp】

    设f[u][i]为u点向下覆盖至少i层并且处理完u的子树的最小代价,f[u][i]为u点向上覆盖至少i层并且处理完u的子树的最小代价 转移的话显然f[u][i]+=f[v][i-1],但是f[u][0 ...

  2. bzoj 4557: [JLoi2016]侦察守卫 树归

    bzoj 4557: [JLoi2016]侦察守卫 设f[x][j]表示覆盖以x为根的子树的所有应该被覆盖的节点,并且以x为根的子树向下j层全部被覆盖的最小代价. 设g[x][j]表示与x距离大于j全 ...

  3. [BZOJ 4033] [HAOI2015] T1 【树形DP】

    题目链接:BZOJ - 4033 题目分析 使用树形DP,用 f[i][j] 表示在以 i 为根的子树,有 j 个黑点的最大权值. 这个权值指的是,这个子树内部的点对间距离的贡献,以及 i 和 Fat ...

  4. [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩)

    [BZOJ 4455] [ZJOI 2016] 小星星 (树形dp+容斥原理+状态压缩) 题面 给出一棵树和一个图,点数均为n,问有多少种方法把树的节点标号,使得对于树上的任意两个节点u,v,若树上u ...

  5. [BZOJ4557][JLOI2016]侦查守卫

    4557: [JLoi2016]侦察守卫 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 297  Solved: 200[Submit][Status ...

  6. BZOJ4557 JLoi2016 侦察守卫 【树形DP】*

    BZOJ4557 JLoi2016 侦察守卫 Description 小R和B神正在玩一款游戏.这款游戏的地图由N个点和N-1条无向边组成,每条无向边连接两个点,且地图是连通的.换句话说,游戏的地图是 ...

  7. BZOJ 4557: [JLoi2016]侦察守卫

    题目大意:每个点有一个放置守卫的代价,同时每个点放置守卫能覆盖到的距离都为d,问覆盖所有给定点的代价是多少. 题解: 树形DP f[x][y]表示x子树中所有点都已经覆盖完,并且x还能向上覆盖y层的最 ...

  8. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  9. BZOJ 2435 道路修建 NOI2011 树形DP

    一看到这道题觉得很水,打了递归树形DP后RE了一组,后来发现必须非递归(BFS) 递归版本84分: #include<cstdio> #include<cstring> #in ...

随机推荐

  1. C++笔记011:C++对C的扩展——变量检测增强

    原创笔记,转载请注明出处! 点击[关注],关注也是一种美德~ 在C语言中重复定义多个同名的变量是合法的,多个同名的全局变量最终会被链接到全局数据区的同一个地址空间上. 在C++中,不允许定义多个同名的 ...

  2. h5跳转到app的实现

    随着业务的增加,可能存在这么一种需求,就是需要从h5中直接跳转到app.如果没有安装app的话,则提示到应用市场或者app store下载安装.不过问题就在这个地方,单纯的用h5是没有方法判断是否安装 ...

  3. 从Oracle导出数据并导入到Hive

    1.配置源和目标的数据连接 源(oracle): 目标(Hive 2.1.1),需要事先将hive的驱动程序导入HHDI的lib目录中. Hive2.1.1需要的jar包如下:可根据自身情况更换had ...

  4. STM32(12)——CAN

    简介: CAN是Controller Area Network,是 ISO 国际标准化的串行通信协议. CAN  控制器根据两根线上的电位差来判断总线电平.总线电平分为显性电平和隐性电平,二者必居其一 ...

  5. Ruby中的类

    初识ruby中的类 只需要简单的两行 class Point end 如果我们此时实例化一个类那么他会有一些自省(introspection)的方法 p = Point.new p.methodes( ...

  6. 如何制作 Ubuntu 系统的 USB 启动盘

    下载 Ubuntu 打开 http://mirrors.ustc.edu.cn 获取安装镜像 --> 获取 ISO 刻录 Ubuntu 到 U 盘 打开 http://rufus.akeo.ie ...

  7. Lambda表达式的语法与如何使用Lambda表达式

    Lambda表达式是对象,是一个函数式接口的实例 如何来写Lambda表达式? 看参数 看返回值 代码实例1: package day2; import jdk.nashorn.internal.co ...

  8. 北京Uber优步司机奖励政策(1月8日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  9. vue.js中引入其他文件export的方法:

    import {GetPosition} from '../../lib/utils'  //找到 该方法的文件路径,然后 用{}拿到 该方法 var position =GetPosition(); ...

  10. 基于套接字通信的简单练习(FTP)

    本项目基于c/s架构开发(采用套接字通信,使用TCP协议) FTP-Socket"""__author:rianley cheng""" 功 ...