题目链接: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即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 #include<set>
 9 #include<map>
10 #include<vector>
11 #include<cctype>
12 #define inf 1e9
13 using namespace std;
14 const int maxn=500005;
15 const int maxd=25;
16
17 int N,D,M,W[maxn];
18 struct edge{ int to,next; }E[maxn<<1];
19 int first[maxn],np,f[maxn][maxd],g[maxn][maxd];
20 bool ob[maxn];
21
22 void _scanf(int &x)
23 {
24     x=0;
25     char ch=getchar();
26     while(ch<'0'||ch>'9') ch=getchar();
27     while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
28 }
29 void add_edge(int u,int v)
30 {
31     E[++np]=(edge){v,first[u]};
32     first[u]=np;
33 }
34 void data_in()
35 {
36     _scanf(N);_scanf(D);
37     for(int i=1;i<=N;i++) _scanf(W[i]);
38     _scanf(M);
39     int x,y;
40     for(int i=1;i<=M;i++){
41         _scanf(x); ob[x]=1;
42     }
43     for(int i=1;i<N;i++){
44         _scanf(x);_scanf(y);
45         add_edge(x,y); add_edge(y,x);
46     }
47 }
48 void DFS(int i,int fa)
49 {
50     for(int d=1;d<=D;d++) f[i][d]=W[i];
51     f[i][D+1]=inf;
52     if(ob[i]) f[i][0]=g[i][0]=W[i];
53     for(int p=first[i];p;p=E[p].next){
54         int j=E[p].to;
55         if(j==fa) continue;
56         DFS(j,i);
57         for(int d=0;d<=D;d++)
58             f[i][d]=min(f[i][d]+g[j][d],f[j][d+1]+g[i][d+1]);
59         for(int d=D;d>=0;d--) f[i][d]=min(f[i][d],f[i][d+1]);
60         g[i][0]=f[i][0];
61         for(int d=1;d<=D;d++) g[i][d]+=g[j][d-1];
62         for(int d=1;d<=D;d++) g[i][d]=min(g[i][d],g[i][d-1]);
63     }
64 }
65 void work()
66 {
67     DFS(1,0);
68     printf("%d\n",f[1][0]);
69 }
70 int main()
71 {
72     data_in();
73     work();
74     return 0;
75 }

View Code

转载于:https://www.cnblogs.com/KKKorange/p/8678650.html

BZOJ 4557 JLOI2016 侦查守卫 树形dp相关推荐

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

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

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

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

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

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

  4. BZOJ 2878: [Noi2012]迷失游乐园( 树形dp )

    一棵树的话直接树形dp(求出往下走和往上走的期望长度). 假如是环套树, 环上的每棵树自己做一遍树形dp, 然后暴力枚举(环上的点<=20)环上每个点跑经过环上的路径就OK了. -------- ...

  5. BZOJ 5252 林克卡特树 —— 树形dp + wqs二分

    题目链接:点我啊╭(╯^╰)╮ 题目大意: 一颗带正负边权的树      删去 kkk 条边后,再任意加上 kkk 条边权为 000 的边      问任意两点简单路径的最大值 解题思路: 题目可以转 ...

  6. BZOJ4557 JLOI2016侦察守卫(树形dp)

    下称放置守卫的点为监控点.设f[i][j]为i子树中深度最大的未被监视点与i的距离不超过j时的最小代价,g[i][j]为i子树中距离i最近的监控点与i的距离不超过j且i子树内点全部被监视时的最小代价. ...

  7. BZOJ.3257.树的难题(树形DP)

    题目链接 状态只与黑.白两点的颜色有关,于是用 \(f[x][i][j]\)表示当前以x为根节点,有\(i\)个黑点\(j\)个白点,使得x子树满足该条件的最小花费. 最后答案就是 \(min\{f[ ...

  8. BZOJ 1123 POI2008 BLO Tarjan+树形DP

    题目大意:给定一张无向图,求每个点被封锁之后有多少个有序点对(x,y)(x!=y,1<=x,y<=n)满足x无法到达y 还是看原题面爽... Tarjan求点双,然后TreeDP即可 时间 ...

  9. BZOJ 2133 切割(树形DP,树上背包)大概是本题全网第一篇题解 >_<【BZOJ 修复工程】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 BZOJ 2133 切割这道题全网搜不到任何一篇题解 >_< 看评测记录也没有几个人AC- ...

最新文章

  1. NoSQL生态系统——一致性RWN协议,向量时钟,gossip协议监测故障
  2. php自定义函数数学计算,ThinkPHP自定义函数解决模板标签加减运算的方法
  3. ES 在数据量很大的情况下如何提高查询效率
  4. 为什么基类的析构函数是虚函数?
  5. windows7怎么安装python库_windows7 下安装Python的PIL库
  6. 线程中消费者生产者的实例代码(synchronized关键字)
  7. AJAX问题:如果SESSION丢失,会直接报错。
  8. 【iOS开发-25】UIDevice查看系统信息,从一个问题開始怎样高速找到自己想要的属性和方法并看懂它...
  9. python下载网页图片并替换_python使用正则表达式分析网页中的图片并进行替换的方法...
  10. 怎么更改坐标轴标题access_excel图表如何修改x坐标轴数值,excel怎么设置横坐标标题...
  11. Jquery引用在线CDN公共资源库
  12. 公告或通知的未读 设计(MySQL Redis)
  13. QC4+充电协议_原来那么多手机支持QC4+快充,小米最多,只是之前用错了充电头...
  14. 【OpenCV 例程 300篇】219. 添加数字水印(盲水印)
  15. Annex-B和AVCC
  16. 【软路由】openwrt 搭建个人NAS-超简单
  17. HTML+CSS个人电影网页设计——电影从你的全世界路过(4页)带音乐特效
  18. 2022年5月8日 解决手机连接电脑无法选择“传输文件”
  19. 实分析笔记(1):康托尔基数理论
  20. 小米8ios图标包下载_小米Max2开发版刷机包(最新官方固件rom包下载)

热门文章

  1. MyEclipse for Mac快捷键
  2. adb 最大连接_手机触屏失效的抢救办法,以及如何利用adb实现PC与手机交互
  3. c语言线程传int值,如何用C语言实现多线程
  4. 睡眠 应该用 a加权 c加权_在神经网络中提取知识:学习用较小的模型学得更好...
  5. 嵩天python笔记_嵩天Python学习笔记-05
  6. C语言中for语句的执行过程是什么?
  7. .net mvc actionresult 返回字符串_ASP.NET Core中的Action的返回值类型
  8. mot数据集_谈谈ReID与MOT的关系
  9. 【渝粤题库】陕西师范大学210019 学前教育科研方法 作业(专升本)
  10. 【渝粤题库】国家开放大学2021春2585城市轨道交通概论答案