[ 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]保安站岗
题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下超市的所有通道呈一棵树的形状:某些通道之间可以互 ...
随机推荐
- 洛谷 P2064 奇妙的汽车
P2064 奇妙的汽车 题目描述 你有着一辆奇妙的汽车,这辆汽车有着自动加速的功能.打个比方吧,第1天你驾驶着它可以行驶a路程,那么第2天你可以让它所走的路程增加到第1天的2~9倍(必须是其中一个整数 ...
- JAVA调用动态链接库(dll)
菜鸡爬坑 基础知识 因为某个东西的keygen我只会在win下生成!! 所以只能出此下策!!之前一直是android下用jni调用so文件,现在试下java在win平台下调用dll 首先还是 ...
- Oracle生成多表触发器sql
--将所有HY开头的表都生成一个更新触发器的脚本('/'是为了连续创建多个触发器而不报错)select 'CREATE OR REPLACE TRIGGER '||table_name||' BEFO ...
- mysql设置datetime默认值为now
mysql设置datetime默认值为now MYSQL-TIMESTAMP数据类型的默认值与自动更新问题 http://blog.csdn.net/scogeek/article/details/5 ...
- 学习swift从青铜到王者之字符串和运算符02
1 字符和字符串初步 var c :Character = "a" 2 构造字符串 let str1 = "hello" let str2 = " ...
- C# 如何修改Form不能修改窗体大小
把窗体的FormBorderSytle改一下就可以了,改成FixedSingle或者Fixed3D都可以
- Android 最火框架XUtils之注解机制具体解释
在上一篇文章Android 最火的高速开发框架XUtils中简介了xUtils的基本用法,这篇文章说一下xUtils里面的注解原理. 先来看一下xUtils里面demo的代码: @ViewInject ...
- easyUI 对话框的关闭事件
有一个easyUI的dialog: <div id="dlg_Add" class="easyui-dialog" style=" width: ...
- ios29--多线程
进程是指在系统中正在运行的一个应用程序(一个程序可以对应多个进程).每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内.比如同时打开迅雷.Xcode,系统就会分别启动2个进程.1个进程要 ...
- UVA - 12345 带修改的莫队
题意显然:给出初始序列,单点修改,区间查询元素的种类. 由于时限过宽,暴力可过. 比较优秀的解法应该是莫队. 带修改的莫队题解可以看https://www.luogu.org/blog/user126 ...