[HNOI 2003] 消防局的设立
2016-02-28 13:04
225 查看
洛谷 2279 03 湖南 消防局的设立
本题地址: http://www.luogu.org/problem/show?pid=2279
题目描述
2020 年,人类在火星上建立了一个庞大的基地群,总共有 n 个基地。起初为了节约材料,人类只修建了 n-1 条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状结构。如果基地 A 到基地 B 至少要经过 d 条道路的话,我们称基地 A 到基地 B 的距离为 d。
由于火星上非常干燥,经常引发火灾,人类决定在火星上修建若干个消防局。消防局只能修建在基地里,每个消防局有能力扑灭与它距离不超过 2 的基地的火灾。
你的任务是计算至少要修建多少个消防局才能够确保火星上所有的基地在发生火灾时,消防队有能力及时扑灭火灾。
输入输出格式
输入格式:
输入文件名为 input.txt。
输入文件的第一行为 n (n<=1000),表示火星上基地的数目。接下来的 n-1 行每行有一个正整数,其中文件第 i 行的正整数为 a[i],表示从编号为 i 的基地到编号为 a[i] 的基地之间有一条道路,为了更加简洁的描述树状结构的基地群,有 a[i]<i。
输出格式:
输出文件名为 output.txt
输出文件仅有一个正整数,表示至少要设立多少个消防局才有能力及时扑灭任何基地发生的火灾。
输入输出样例
输入样例 #1:
6
1
2
3
4
5
输出样例 #1:
2
树形 dp,就是 dfs+ 向上更新。比较难想到的是状态,这里每种节点用了 5 个 dp[v][0~4],分别代表某个节点 v** 至少覆盖到孙子、儿子、自己、父亲、祖父节点 ** 所需的消防站个数。
然后是状态转移。从覆盖到祖父开始,很容易看出来,这个节点 v 自己一定要涂色(设消防局),向上两个距离,向下两个距离,所以 v 的儿子们只要管到各自的孙子就行了。画张图理解下:
如果要求覆盖到父亲,那么一种情况就是同上,因为这 5 种状态是包含的关系,而不是排斥的。第二种情况,就是 v 的某个儿子覆盖到它的祖父(一起唱:儿子的爷爷是爸爸),由于那个儿子可以向上两个距离,同时也可以绕下来覆盖 v 的其他的儿子节点,从而 v 的其他儿子只要管到各自的儿子就行了。
如果要求覆盖到自己,第一种情况也包含在上面。第二种情况,v 的某个儿子覆盖到 v(就是他的父亲),其余的儿子管到自身。
之后的以此类推←_←具体见代码
本题地址: http://www.luogu.org/problem/show?pid=2279
题目描述
2020 年,人类在火星上建立了一个庞大的基地群,总共有 n 个基地。起初为了节约材料,人类只修建了 n-1 条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状结构。如果基地 A 到基地 B 至少要经过 d 条道路的话,我们称基地 A 到基地 B 的距离为 d。
由于火星上非常干燥,经常引发火灾,人类决定在火星上修建若干个消防局。消防局只能修建在基地里,每个消防局有能力扑灭与它距离不超过 2 的基地的火灾。
你的任务是计算至少要修建多少个消防局才能够确保火星上所有的基地在发生火灾时,消防队有能力及时扑灭火灾。
输入输出格式
输入格式:
输入文件名为 input.txt。
输入文件的第一行为 n (n<=1000),表示火星上基地的数目。接下来的 n-1 行每行有一个正整数,其中文件第 i 行的正整数为 a[i],表示从编号为 i 的基地到编号为 a[i] 的基地之间有一条道路,为了更加简洁的描述树状结构的基地群,有 a[i]<i。
输出格式:
输出文件名为 output.txt
输出文件仅有一个正整数,表示至少要设立多少个消防局才有能力及时扑灭任何基地发生的火灾。
输入输出样例
输入样例 #1:
6
1
2
3
4
5
输出样例 #1:
2
思路
很有意思的一道(shui)题,但是对于某蒟蒻来说,也是想了很久。。。T_T树形 dp,就是 dfs+ 向上更新。比较难想到的是状态,这里每种节点用了 5 个 dp[v][0~4],分别代表某个节点 v** 至少覆盖到孙子、儿子、自己、父亲、祖父节点 ** 所需的消防站个数。
然后是状态转移。从覆盖到祖父开始,很容易看出来,这个节点 v 自己一定要涂色(设消防局),向上两个距离,向下两个距离,所以 v 的儿子们只要管到各自的孙子就行了。画张图理解下:
如果要求覆盖到父亲,那么一种情况就是同上,因为这 5 种状态是包含的关系,而不是排斥的。第二种情况,就是 v 的某个儿子覆盖到它的祖父(一起唱:儿子的爷爷是爸爸),由于那个儿子可以向上两个距离,同时也可以绕下来覆盖 v 的其他的儿子节点,从而 v 的其他儿子只要管到各自的儿子就行了。
如果要求覆盖到自己,第一种情况也包含在上面。第二种情况,v 的某个儿子覆盖到 v(就是他的父亲),其余的儿子管到自身。
之后的以此类推←_←具体见代码
代码
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int MAXN = 3000, INF = 0x3f3f3f3f; int head[MAXN], next[MAXN], to[MAXN], pa[MAXN], tot, N; bool lf[MAXN]; //是否为叶子节点 int dp[MAXN][10]; //树状dp //dp[v] = 从n=0时为v的孙子节点,到n=4时为v的祖父节点,覆盖到第n层所需的最少数目 void init(){ memset(head, -1, sizeof(head)); tot = 0; } void add2(int a, int b){ to[tot] = b; next[tot] = head[a]; head[a] = tot++; to[tot] = a; next[tot] = head[b]; head[b] = tot++; } void pushup(int v){ //将v的子节点的信息更新到v dp[v][4] = 1; int min1 = INF, min2 = INF; for(int i = head[v]; ~i; i = next[i]){ int u = to[i]; if(u != pa[v]){ dp[v][4] += dp[u][0]; // dp[v][3] += dp[u][1]; // dp[v][2] += dp[u][2]; dp[v][1] += dp[u][2]; dp[v][0] += dp[u][1]; min1 = min(min1, dp[u][4] - dp[u][1]); min2 = min(min2, dp[u][3] - dp[u][2]); } } dp[v][3] = dp[v][0] + min1; dp[v][2] = dp[v][1] + min2; for(int i = 3; i >= 0; --i){ dp[v][i] = min(dp[v][i], dp[v][i+1]); } } void dfs(int v){ if(lf[v]){ dp[v][4] = dp[v][3] = dp[v][2] = 1; return; } for(int i = head[v]; ~i; i = next[i]){ int u = to[i]; if(u != pa[v]){ dfs(u); } } pushup(v); } int main(){ freopen("in.txt", "r", stdin); scanf("%d", &N); if(N == 0){ printf("0\n"); return 0; } init(); for(int i = 2; i <= N; ++i){ int p; scanf("%d", &p); pa[i] = p; lf[p] = false; add2(i, p); } dfs(1); printf("%d\n", dp[1][2]); return 0; }
相关文章推荐
- poj 3278 Catch That Cow bfs
- vfork Function
- [译]如何防止elasticsearch的脑裂问题
- Flatten Binary Tree to Linked List
- ubuntu安装python
- 【Codeforces Round 340 (Div 2)C】【暴力排序枚举】Watering Flowers 2个灌溉器灌溉所有点最小的rr+RR
- [效率神技]Intellij 的快捷键和效率技巧|系列一|常用快捷键
- 大型网站架构系列:负载均衡详解(2)
- Database Replay wrc命令报错ORA-15552: workload replay client cannot login to database server
- Manthan, Codefest 16 E. Startup Funding ST表 二分 数学
- 自定义dialog类
- genymotion无法下载解决方法
- 【Codeforces Round 340 (Div 2)B】【简单题】Chocolate 巧克力划分方案数 每段恰有一个坚果
- java重拍 https://www.zhihu.com/question/34387716/answer/76029594
- Uiautomator编译运行的自动化
- SDK无法更新
- andorid build tools 19.1
- LeetCode OJ 1. Two Sum
- mySql乱码
- visualSVN server库迁移