P2458 [SDOI2006]保安站岗[树形dp]
题目描述
五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序。
已知整个地下超市的所有通道呈一棵树的形状;某些通道之间可以互相望见。总经理要求所有通道的每个端点(树的顶点)都要有人全天候看守,在不同的通道端点安排保安所需的费用不同。
一个保安一旦站在某个通道的其中一个端点,那么他除了能看守住他所站的那个端点,也能看到这个通道的另一个端点,所以一个保安可能同时能看守住多个端点(树的结点),因此没有必要在每个通道的端点都安排保安。
编程任务:
请你帮助超市经理策划安排,在能看守全部通道端点的前提下,使得花费的经费最少。
输入输出格式
输入格式:
第1行 n,表示树中结点的数目。
第2行至第n+1行,每行描述每个通道端点的信息,依次为:该结点标号i(0<i<=n),在该结点安置保安所需的经费k(<=10000),该边的儿子数m,接下来m个数,分别是这个节点的m个儿子的标号r1,r2,...,rm。
对于一个n(0 < n <= 1500)个结点的树,结点标号在1到n之间,且标号不重复。
输出格式:
最少的经费。
如右图的输入数据示例
输出数据示例:

输入输出样例
输入样例#1:
6
1 30 3 2 3 4
2 16 2 5 6
3 5 0
4 4 0
5 11 0
6 5 0
输出样例#1:
25
说明
样例说明:在结点2,3,4安置3个保安能看守所有的6个结点,需要的经费最小:25
解析:
写完这道题,真的感觉提高了不少!
看到题解写的都是三种状态,虽然我也写了三种状态的解法(比较容易理解),但是咱教练曰:四种状态的也可以。于是便来一发四种状态的(其实本质上也可以化为三种状态,二者无本质区别)。
根据题意,我们得出对于除叶子节点外任意的节点\(x\),可以有四种情况:
若\(x\)的位置的费用为\(c_x\),其父节点为\(fa\)。
- \(x\)的位置没有保安,\(fa\)的位置有保安
- \(x\)的位置没有保安,\(fa\)的位置没有保安
- \(x\)的位置有保安,\(fa\)的位置有保安
- \(x\)的位置有保安,\(fa\)的位置没有保安
设\(dp[x][0/1/2/3]\)表示在以\(x\)为根的子树中,使得每个端点都被覆盖了的最小花费。其中每一种状态对应上面的每一种情况。
注意一下下文提到的状态与情况的区别。
一、
首先考虑\(1\)情况,对于这样的\(x\),假设它任意一个子节点为\(y\),那么必然有:
\(dp[x][0]=\sum_{y\in tree(x)} min(dp[y][1],dp[y][3])\)
即,若要使情况\(1\)成立,那么必然要从使得它成立的状态(即\(y\)的父节点没有保安)转移过来。
二、
我们先考虑\(3、4\)情况,因为他们比较像。。。
我估摸着这个状态是可以合并的,因为无论\(x\)的\(fa\)有没有保安,都无所谓,不影响转移。
容易得出:
\(dp[x][2/3]=\sum_{y\in{tree(x)}} min(dp[y][0],dp[y][2])+c_x\)
即,若要使得情况\(3、4\)成立,那么\(y\)的\(fa\)就要有保安。
三、
这里就比较难理解,但是跟其它题解是同一个思路。
我们首先明确我们对状态的刻画:设\(dp[x][0/1/2/3]\)表示在以\(x\)为根的子树中,每个端点都被覆盖了所能得到的最小花费。
对于情况\(2\),有两种决策,即
- 选择从子节点\(y\)的第\(1\)种状态转移过来(\(dp[y][1]\)),这时\(y\)位置没有保安。
- 选择从子节点\(y\)的第\(3\)种状态转移过来(\(dp[y][3]\)),这时\(y\)位置有保安。
可以预见的是,如果对于一个节点\(x\),把它作为一个根节点,它的所有子节点\(y\)都不放置保安时得到最优解(即\(x\)阶段全部从\(dp[y][1]\)转移过来),那么显然这样的情况是不符合我们刻画的状态的(根节点\(x\)未被覆盖到)。
所以我们就要特判一下,一旦出现这种情况,我们就要贪心地去使得当前状态在我们规定的意义下成立。
即,寻找对花费贡献最小的那个\(dp[y][3]\),拿它做转移到\(x\)。
怎么做呢?很简单,我们把最小的\(dp[y][3]-dp[y][1]\)加进原先我们得出的无法成立的状态中就行了。
证明的话,其实想一想,这个差值其实就是将原先的一个转移\(dp[y][1]\)变成\(dp[y][3]\)的时候的变化值。
建议好好品味这道题,能有不错的收获。
参考代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 2010
#define MOD 2520
#define E 1e-12
#define INF 0x3f3f3f3f
using namespace std;
//start from 1
struct rec{
int next,ver;
}g[N<<1];
int head[N],tot,n,dp[N][4],a[N];
bool v[N];
inline int read()
{
int f=1,x=0;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
void add(int x,int y)
{
g[++tot].ver=y;
g[tot].next=head[x],head[x]=tot;
}
void calc(int x)
{
v[x]=1;
int sum=0,minn=INF;
dp[x][2]=a[x];dp[x][3]=a[x];
for(int i=head[x];i;i=g[i].next){
int y=g[i].ver;
if(v[y]) continue;
calc(y);
//0fa有self没有,1fa没有self没有,2fa有self有,3fa没有self有
dp[x][2]+=min(dp[y][0],dp[y][2]);
dp[x][3]+=min(dp[y][0],dp[y][2]);
if(dp[y][1]>dp[y][3]) sum++;
else minn=min(minn,dp[y][3]-dp[y][1]);
dp[x][0]+=min(dp[y][1],dp[y][3]);
dp[x][1]+=min(dp[y][1],dp[y][3]);
}
if(!sum) dp[x][1]+=minn;
}
int main()
{
n=read();
for(int i=1;i<=n;i++){
int ii,k;
ii=read(),a[ii]=read(),k=read();
for(int t=1;t<=k;t++){
int y;
y=read();
add(ii,y),add(y,ii);
}
}
calc(1);
cout<<min(dp[1][1],dp[1][3])<<endl;//根节点不会有父节点嘛,这个好理解
return 0;
}
P2458 [SDOI2006]保安站岗[树形dp]的更多相关文章
- Luogu P2458 [SDOI2006]保安站岗(树形dp)
P2458 [SDOI2006]保安站岗 题意 题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下 ...
- C++ 洛谷 P2458 [SDOI2006]保安站岗 from_树形DP
P2458 [SDOI2006]保安站岗 没学树形DP的,看一下. 题目大意:一棵树有N个节点,现在需要将所有节点都看守住,如果我们选择了节点i,那么节点i本身,节点i的父亲和儿子都会被看守住. 每个 ...
- Luogu P2458 [SDOI2006]保安站岗【树形Dp】
题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下超市的所有通道呈一棵树的形状:某些通道之间可以互 ...
- 洛谷 P2458 [SDOI2006]保安站岗
题目传送门 解题思路: 树形DP 可知一个点被控制有且仅有一下三种情况: 1.被父亲节点上的保安控制 2.被儿子节点上的保安控制 3.被当前节点上的保安控制 我们设dp[0/1/2][u]表示u节点所 ...
- [Luogu][P2458] [SDOI2006]保安站岗
题目链接 看起来似乎跟最小点覆盖有点像.但区别在于: 最小点覆盖要求所有边在其中,而本题要求所有点在其中. 即:一个点不选时,它的儿子不一定需要全选. 画图理解: 对于这样一幅图,本题中可以这样选择: ...
- [luogu 2458][SDOI2006]保安站岗
题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下超市的所有通道呈一棵树的形状:某些通道之间可以互 ...
- [SDOI2006] 保安站岗
题目链接 第一遍不知道为什么就爆零了…… 第二遍改了一下策略,思路没变,结果不知道为什么就 A 了??? 树形 DP 经典问题:选择最少点以覆盖树上所有点(边). 对于本题,设 dp[i][0/1][ ...
- 洛谷【P2458】[SDOI2006]保安站岗 题解 树上DP
题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下超市的所有通道呈一棵树的形状:某些通道之间可以互 ...
- [Luogu2458][SDOI2006]保安站岗
题目描述 五一来临,某地下超市为了便于疏通和指挥密集的人员和车辆,以免造成超市内的混乱和拥挤,准备临时从外单位调用部分保安来维持交通秩序. 已知整个地下超市的所有通道呈一棵树的形状:某些通道之间可以互 ...
随机推荐
- consul(一)什么是consul
1. consul的基本介绍 在分布式架构中,服务治理是一个重要的问题.在没有服务治理的分布式集群中,各个服务之间通过手工或者配置的方式进行服务关系管理,遇到服务关系变化或者增加服务的时候,人肉配置极 ...
- Linux 下 安装 Jmeter
Linux下安装jmeter 1.1 下载JMeter 官方网站下载最新版本: http://jmeter.apache.org/download_jmeter.cgi 两个只是解压方式不一样而 ...
- 2019年春季学期《C语言程序设计II》课程总结
2019年春季学期<C语言程序设计II>课程总结 1.课程情况 教学内容 课堂小结 作业安排 优秀作业 备注 1.开学谈心 2.测验数据类型.运算符与表达式的自学情况,并讲解测验题目3.第 ...
- [.Net Core] - 当 .Net Core 版本由 1.x 升级至 2.x 后,Cookie 使用方式变更
背景 Asp.Net Core 项目升级至 2.x 版本后,Cookie 验证方式需要进行更新. 升级前:.Net Core 1.x Startup.cs public void Configure( ...
- Pythn基础课程笔记day03_学习内容概要及作业讲解
第三天_学习内容概要 今日内容概要 1.整形 2.布尔类型 3.字符串 内容回顾和补充 内容回顾 利用思维导图,罗列复习自己学习的内容,巩固知识点. xmind 软件 processon 网站 补充 ...
- JPA逆向工程
1.1 说明 所谓的逆向工程就是通过数据库的结构生成代码. 目的:提高开发的效率 1.2 步骤 1.2.1 第一步:创建JPA项目 (1)创建项目 (2)指定项目名.JPA版本 (3)完成创建 1.2 ...
- flutter从入门到精通四
widget Flutter 从 React 中吸取灵感(如果有react的编程经验,会很容易理解flutter),通过现代化框架创建出精美的组件. 它的核心思想是用 widget 来构建你的 UI ...
- Springmvc的@ResponseBody方法返回Model时404:跳转jsp视图
我有一个控制器方法,添加了@ResponseBody注解 @GetMapping(value = "/users") @ResponseBody public Map<Str ...
- 应用程序池优化配置方案(IIS7、IIS7.5)
定义: 是将一个或多个应用程序链接到一个或多个工作进程集合的配置,该池中的应用程序与其他应用程序被工作进程边界分隔, 一.一般优化方案 1.基本设置 [1]队列长度:默认1000,将原来的队列长度65 ...
- Authentication failed for "http://xxxxxx"
1.配置用户信息 git config --global user.name [username] git config --global user.email [email] 2.查询用户信息 ...