【题解】警位安排( 树形 DP)
【题目描述】
一个重要的基地被分成了 n 个连通的区域 , 出于某种原因 , 这个基地以某一个区域为核
心,呈一树形分布。
在每个区域里安排警卫的费用是不同的,而每个区域的警卫都可以望见其相邻的区域 。
如果一个区域有警卫或是被相邻区域的警卫望见 , 那它就是安全的 , 你的任务是 : 在确保所
有的区域安全的状态下,使总费用最小。
【输入格式】
第一行 n ,表示树中结点的数目。
接下来 n 行,每行依次是:区域的编号;在此安排警卫的费用;它的子结点的个数 m ,
然后往后 m 个数,为它的子结点编号。
【输出格式】
一行一个数,为最小费用。
【输入样例】
6
1 30 3 2 3 4
2 16 2 5 6
3 5 0
4 4 0
5 11 0
6 5 0
【输出样例】
25
#include <cstdlib>
#include <fstream>
#include <cstring>
#include <iostream> using namespace std; ifstream fin("security.in");
ofstream fout("security.out"); int cnt_node=;//点的个数
bool fuqin[]={false};//判断是否有父节点 int head[]={},cnt=;
struct liansi{
int to;
int nxt;
};
liansi lian_son[]={};//链式前向星 int paying[]={};//每个警卫处要安排警察的费用
int p_state[][]={}; //状态 void add(int a,int b);//链式前向星
void plan(int size,int state); void add(int a,int b){
lian_son[++cnt].to=b;
lian_son[cnt].nxt=head[a];
head[a]=cnt;
return;
} void plan(int size,int state){
if(head[size]==-){//当前节点为数最底部
p_state[size][state]=;//如果状态为父亲看守 花费为0
if(state==){
p_state[size][]=paying[size]; //状态为自己看守 ,花费为自己安排警卫所付的钱
}
return;
} if(state==){//当前节点自己安排警卫
int sum=;
for(int hao=head[size];hao!=-;hao=lian_son[hao].nxt){
int minn=0x7fffff;
int son=lian_son[hao].to; if(p_state[son][]<)plan(son,);//它的儿子可以让父亲看守
minn=min(minn,p_state[son][]);//打擂 求最小 if(p_state[son][]<)plan(son,); //可以自己看守(为便利子孙)
minn=min(minn,p_state[son][]);//打擂 求最小 if(head[son]!=-){//它的儿子也可以让自己儿子看守 这里是说它的儿子有儿子
if(p_state[son][]<)plan(son,);
minn=min(minn,p_state[son][]); //打擂 求最小
}
sum+=minn;//加上所以儿子所用最小值
}
p_state[size][]=sum+paying[size];//再加上自己的安排警卫的钱,为当前节点安排警卫所花费最小金额
} if(state==){//如果让父亲看守
int sum=;
for(int hao=head[size];hao!=-;hao=lian_son[hao].nxt){
int minn=0x7fffff;
int son=lian_son[hao].to; if(p_state[son][]<)plan(son,);//当前节点的儿子要么自己看守
minn=min(minn,p_state[son][]); if(head[son]!=-){
if(p_state[son][]<)plan(son,);//要么有儿子就让儿子看守
minn=min(minn,p_state[son][]);
}
sum+=minn;
}
p_state[size][]=sum;
} if(state==){//表示当前节点由某一儿子看守
int Min=0x7fffff;
for(int hao=head[size];hao!=-;hao=lian_son[hao].nxt){
int sum=, meijv=lian_son[hao].to; //枚举看守儿子节点 for(int hao2=head[size];hao2!=-;hao2=lian_son[hao2].nxt){
int minn=0x7fffff, son=lian_son[hao2].to; if(son!=meijv){//计算非枚举子节点所要花费最小值 if(p_state[son][]<)plan(son,);
minn=min(minn,p_state[son][]);
if(head[son]!=-){
if(p_state[son][]<)plan(son,);
minn=min(minn,p_state[son][]);
}
sum+=minn;
}
}
if(p_state[meijv][]<)plan(meijv,);//计算枚举看守儿子看守的最小值
Min=min(Min,sum+p_state[meijv][]);
}
p_state[size][]=Min;
} return;
} int main(){
fin>>cnt_node; memset(head,-,sizeof(head)); for(int x=;x<=cnt_node;x++){
int s1ze=,paid=,cnt_son=;
fin>>s1ze>>paid>>cnt_son;//输入编号花费与子节点个数
paying[s1ze]=paid;
for(int y=;y<=cnt_son;y++){
int son=;
fin>>son;
fuqin[son]=true;//表示此编号有父节点
add(s1ze,son); //用链式前向星将父节点与子节点连接起来
}
} int gen=;//根
for(int i=;i<=cnt_node;i++){
if(fuqin[i]==false){//如果一个点没有父节点
gen=i;//那么它就是根
break;
}
} memset(p_state,-,sizeof(p_state));//将所有状态默认为-1 plan(gen,); //表示它自己放警卫 自己看守
plan(gen,);//表示让它儿子放警卫 让儿子看守
int ans=min(p_state[gen][],p_state[gen][]);//比较哪种费用最低
cout<<ans;
fout<<ans;
return ;
} /*
核心思路:
划分阶段:
0.由父亲看守,那么它的儿子要么自己看守,要么让它儿子看守
1.有由自己看守,那么自己的儿子可以不看守,也可以看守便利子孙
2.由某一个儿子看守,其它儿子照样可以选择自己看守,还是由自己的儿子看守
*/
【题解】警位安排( 树形 DP)的更多相关文章
- codeforces766E Mahmoud and a xor trip(按位统计+树形DP)
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- 3月28日考试 题解(二分答案+树形DP+数学(高精))
前言:考试挂了很多分,难受…… --------------------- T1:防御 题意简述:给一条长度为$n$的序列,第$i$个数的值为$a[i]$.现让你将序列分成$m$段,且让和最小的一段尽 ...
- 【BZOJ1864】[Zjoi2006]三色二叉树 树形DP
1864: [Zjoi2006]三色二叉树 Description Input 仅有一行,不超过500000个字符,表示一个二叉树序列. Output 输出文件也只有一行,包含两个数,依次表示最多和最 ...
- POJ1947 - Rebuilding Roads(树形DP)
题目大意 给定一棵n个结点的树,问最少需要删除多少条边使得某棵子树的结点个数为p 题解 很经典的树形DP~~~直接上方程吧 dp[u][j]=min(dp[u][j],dp[u][j-k]+dp[v] ...
- hdu_Anniversary party_(树形DP入门题)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 题意:有N个人,N-1个人有自己的上司,每个人有一个快乐值,如果这个人参加了聚会,那么这个人的直 ...
- bzoj 4871: [Shoi2017]摧毁“树状图” [树形DP]
4871: [Shoi2017]摧毁"树状图" 题意:一颗无向树,选两条边不重复的路径,删去选择的点和路径剩下一些cc,求最多cc数. update 5.1 : 刚刚发现bzoj上 ...
- hdu5293 Tree chain problem 树形dp+线段树
题目:pid=5293">http://acm.hdu.edu.cn/showproblem.php?pid=5293 在一棵树中,给出若干条链和链的权值.求选取不相交的链使得权值和最 ...
- hdu3586 Information Disturbing 【树形dp】
题目链接 hdu3586 题解 二分 + 简单的树形dp 我正有练一下dp的必要了 #include<iostream> #include<cstdio> #include&l ...
- Hackrank Kingdom Division 树形DP
题目链接:传送门 题意: 给你一棵树,n个点 每个点可以染成红色和蓝色 但是红色的点与其相邻的点中必须有红色节点,蓝色也是 问你有多少种染色的方案 题解: 树形dp 先转化为有根树,取1为根 设定dp ...
随机推荐
- C++单元测试2
这里再对上一篇<C++单元测试>进行技巧补充. 我们知道对动态链接库(lib和dll)的测试是比较简单的,我这里主要对需要注意的地方说明一下. 1.建议单独创建单元测试解决方案(不是创建项 ...
- Ubuntu系统、开发环境配置
在VMware10下安装成功了Ubuntu 13.10桌面版,刚安装完需要配置很多内容,下面为记录: 1. 更新源: 想了解更新地址的可以查看apt-get的源列表文件 $ sudo gedit /e ...
- Maya pywin32
Maya 2011 – 2013 64-bit: maya-64-bit-pywin32.zipMaya 2011 – 2013 32-bit: maya-32-bit-pywin32.zipMaya ...
- 趣味C程序100.1 .2 绘制正弦曲线
说明:1.本问题来源于<C语言经典.趣味.实用程序设计编程百例精解>,所有程序为本人自己编写.与原程序不同之处作有标记. 2.本系列所有程序均使用codeblocks编译,操作系统为Win ...
- netsat -ano 查看已占用的端口以及tomcat出现端口被占或者启动失败问题
A.在DOS命令下:输入netstat -ano——回车,可以查看已占用的端口,记下端口的PID,然后打开任务管理器,点查看,选择列,勾选PID确定,找到对应的PID,结束进程,如果结束不了或者结束后 ...
- JS匿名执行函数
一.匿名函数的创建 第一种:(调用sum后可执行) var sum=function(x,y){ return x+y; } 第二种:(可自执行) void function(x,y){ }(1,2) ...
- 从内部剖析C# 集合之---- HashTable
这是我在博客园的第一篇文章,写的不好或有错误的地方,望各位大牛指出,不甚感激. 计划写几篇文章专门介绍HashTable,Dictionary,HashSet,SortedList,List 等集合对 ...
- JavaScript中url 传递参数(特殊字符)解决方法
有些符号在URL中是不能直接传递的,如果要在URL中传递这些特殊符号,那么就要使用他们的编码了.下表中列出了一些URL特殊符号及编码 十六进制值1. + URL 中+号表示空格 %2B2. 空格 UR ...
- [BZOJ 3129] [Sdoi2013] 方程 【容斥+组合数取模+中国剩余定理】
题目链接:BZOJ - 3129 题目分析 使用隔板法的思想,如果没有任何限制条件,那么方案数就是 C(m - 1, n - 1). 如果有一个限制条件是 xi >= Ai ,那么我们就可以将 ...
- [BZOJ 1733] [Usaco2005 feb] Secret Milking Machine 【二分 + 最大流】
题目链接:BZOJ - 1733 题目分析 直接二分这个最大边的边权,然后用最大流判断是否可以有 T 的流量. 代码 #include <iostream> #include <cs ...