[ SDOI 2006 ] 保安站岗
\(\\\)
Description
给出一棵 \(n\) 个节点以 \(1\) 为根的树,一个节点的覆盖半径是 \(1\) ,点有点权 \(val_x\) 。
选择一些点,使得点权和最小,同时每个节点要么被选择要么被周围的点覆盖。
- \(n\le 1500,0\le val_x\le 10^4\)
\(\\\)
Solution
树形DP 的讨论。
注意到覆盖有可能呈现出两层都没有选点的情况 (下面被子树覆盖,上面被父节点覆盖),所以状态设计要注意。
设\(f[i][0/1/2]\),表示节点 \(i\) 及其子树的覆盖代价,明确定义:
- \(0\) 表示选择自己,覆盖整个子树的最小代价
- \(1\) 表示第 \(i\) 个节点被自己的子树的根节点覆盖,不选择自己的最小代价
- \(2\) 表示第 \(i\) 个节点被父节点覆盖,此时当前节点的所有子树都已经完成覆盖的最小代价
转移讨论起来就很方便了。
\(0\) :显然要选自己,所以所有子树选什么都合法,对每个子树累加 \(min(f[v][0],f[v][1],f[v][2])\) 。
\(2\):不选自己,子树内部显然不能再向当前点提出需求,所以对子树累加 \(min(f[v][0],f[v][1])\) 。
\(1\) 的转移有点意思。
如果我们贪心的选,选择 \(0\) 状态最小的子树,剩下的子树都选 \(1\) 状态,不一定是最优的。
因为这个 \(0\) 状态最小的子树,他的 \(1\) 状态可能会更小的多,这个差值完全能够允许另一个 \(1\) 状态变成 \(0\) 状态。
\(\\\)
所以考虑替换, \(yy\) 出来一个比较好的写法。
先对所有子树求出 \(sum=min(f[v][0],f[v][1])\) 。
同时维护 \(tmp=min(\ f[v][0]-\min(f[v][0],f[v][1])\ )\)。
\(\\\)
这个 \(sum\) 的含义是,不考虑子树覆盖当前节点, 子树内部覆盖的最小值,可以发现其实就是 \(f[u][2]\) 。
\(tmp\) 的含义就是,把这个 \(sum\) 集合里的任意一个点不管之前选的什么,现在变成 \(0\) 状态的最小代价。
如果之前求 \(sum\) 的时候选了一个 \(0\) 状态,那么这个 \(tmp\) 显然是 \(0\) 。
如果之前没有选到任意一个 \(0\) 状态,那么这个 \(tmp\) 就是所有的 \(1\) 状态里,变成 \(0\) 状态的最小代价。
所以有 \(f[v][1]=f[v][2]+tmp\) 。
\(\\\)
Code
#include<cmath>
#include<cstdio>
#include<cctype>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 1510
#define gc getchar
#define R register
#define inf 2000000000
using namespace std;
inline int rd(){
int x=0; bool f=0; char c=gc();
while(!isdigit(c)){if(c=='-')f=1;c=gc();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=gc();}
return f?-x:x;
}
int n,m,tot,hd[N],f[N][3],val[N];
struct edge{int to,nxt;}e[N<<1];
inline void add(int u,int v){
e[++tot].to=v; e[tot].nxt=hd[u]; hd[u]=tot;
}
//0: 选自己
//1: 选子树内覆盖自己
//2:选父节点覆盖自己
void dfs(int u,int fa){
int mn=inf;
f[u][0]=val[u]; f[u][2]=0;
for(R int i=hd[u],v;i;i=e[i].nxt)
if((v=e[i].to)!=fa){
dfs(v,u);
f[u][0]+=min(f[v][2],min(f[v][1],f[v][0]));
f[u][2]+=min(f[v][1],f[v][0]);
mn=min(mn,f[v][0]-min(f[v][1],f[v][0]));
}
f[u][1]=f[u][2]+mn;
}
int main(){
n=rd();
memset(f,0x3f,sizeof(f));
for(R int i=1,u,cnt;i<=n;++i){
u=rd(); val[u]=rd(); cnt=rd();
for(R int j=1,v;j<=cnt;++j){v=rd();add(u,v);add(v,u);}
}
dfs(1,0);
printf("%d\n",min(f[1][0],f[1][1]));
return 0;
}
[ SDOI 2006 ] 保安站岗的更多相关文章
- 【Luogu2458】保安站岗(动态规划)
[Luogu2458]保安站岗(动态规划) 题面 题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地 ...
- C++ 洛谷 P2458 [SDOI2006]保安站岗 from_树形DP
P2458 [SDOI2006]保安站岗 没学树形DP的,看一下. 题目大意:一棵树有N个节点,现在需要将所有节点都看守住,如果我们选择了节点i,那么节点i本身,节点i的父亲和儿子都会被看守住. 每个 ...
- 【题解】保安站岗[P2458]皇宫看守[LOJ10157][SDOI2006]
[题解]保安站岗[P2458]皇宫看守[LOJ10157][SDOI2006] 传送门:皇宫看守\([LOJ10157]\) 保安站岗 \([P2458]\) \([SDOI2006]\) [题目描述 ...
- Luogu P2458 [SDOI2006]保安站岗(树形dp)
P2458 [SDOI2006]保安站岗 题意 题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下 ...
- 洛谷【P2458】[SDOI2006]保安站岗 题解 树上DP
题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下超市的所有通道呈一棵树的形状:某些通道之间可以互 ...
- [luogu 2458][SDOI2006]保安站岗
题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下超市的所有通道呈一棵树的形状:某些通道之间可以互 ...
- 洛谷P2458 保安站岗
传送门啦 分析: 树形dp刚刚入门,这是我做的第一个一个点同时受父亲节点和儿子节点控制的题目. 由于这个题中某一个点放不放保安与父亲和儿子都有关系(因为线段的两个端点嘛),所以我们做题时就要考虑全面. ...
- Luogu P2458 [SDOI2006]保安站岗【树形Dp】
题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下超市的所有通道呈一棵树的形状:某些通道之间可以互 ...
- [Luogu2458][SDOI2006]保安站岗
题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下超市的所有通道呈一棵树的形状:某些通道之间可以互 ...
随机推荐
- 对一个deb包的解压、改动、又一次打包全过程方法
/********************************************************************* * Author : Samson * Date ...
- Unix时间戳(Unix timestamp)转换
http://tool.chinaz.com/Tools/unixtime.aspx 如何在不同编程语言中获取现在的Unix时间戳(Unix timestamp)? Java time JavaScr ...
- C# .NET 如何修改代码字体
工具-选项-字体和颜色
- FFmpeg的HEVC解码器源码简单分析:概述
===================================================== HEVC源码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpeg ...
- 一个有趣的问题:ls -l显示的内容中total究竟是什么?
当我们在使用ls -l的命令时,我们会看到例如以下类似的信息. 非常多人可能对于第一行的total 12的数值并非非常在意,可是你是否想过,它到底是什么意思? man中的说明,我们能够看出total的 ...
- 关于camera senor的power引脚问题
<CamDevie> <HardWareInfo> <Sensor> <SensorName name="OV5640" >< ...
- POJ1664 计数 DP
题目传送门 http://poj.org/problem?id=1664 设$dp[i][j]$表示$i$个苹果放在$j$个盘子里的总数 $1.$ 当 苹果数 小于 盘子数 $(M < N) ...
- 并不对劲的bjwc d4t1
先膜一波宽神Orz%%%%% 拿到这题的第一反应就是:暴力啊!感觉神奇的钟点并没有什么性质,可能卡常能过吧……所以就写了一个O(22^3*59^3)的暴力.本来想打表,但是发现代码长度有限制,写不下. ...
- Joseph问题 (线段树)
Joseph问题似乎是入门题,就是那个报数出圈的问题,不过它暴力模拟的复杂度是O(nm)的,如果题目的数据范围达到了30000,那就超时了.怎么用线段树维护呢? 我们可以这么考虑,每次我们其实要查询在 ...
- linux下的zookeeper启动
zookeeper的安装目录:/usr/local/zookeeper-3.4.6/bin/zkServer.sh; 配置文件路径:../conf/zoo.cfg 端口 :2181: ZooKeepe ...