NKOJ1472 警卫安排

P1472警卫安排

 
时间限制 : 10000 MS   空间限制 : 65536 KB
问题描述

一个重要的基地被分为n个连通的区域。出于某种神秘的原因,这些区域以一个区域为核心,呈一颗树形分布。
在每个区域安排警卫所需要的费用是不同的,而每个区域的警卫都可以望见其相邻的区域,只要一个区域被一个警卫望见或者是安排有警卫,这个区域就是安全的。你的任务是:在确保所有区域都是安全的情况下,找到安排警卫的最小费用。

输入格式

第一行n,表示树中结点的数目。
接下来的n行描述了n个区域的信息,每一行包含的整数依次为:区域的标号i(0<i<=n),在区域i安排警卫的费用k,区域i的子结点数目m,接下来m个数为区域i的子结点编号。

输出格式

一行一个整数,为最小的安排费用。

样例输入

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

提示

对于所有的数据,0<n<=720。

【题解】

——by 朱全民

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <cmath>
  6 #include <algorithm>
  7 #define min(a, b) ((a) < (b) ? (a) : (b))
  8 #define max(a, b) ((a) > (b) ? (a) : (b))
  9
 10 inline void read(int &x)
 11 {
 12     x = 0;char ch = getchar(), c = ch;
 13     while(ch < ‘0‘ || ch > ‘9‘)c = ch, ch = getchar();
 14     while(ch <= ‘9‘ && ch >= ‘0‘)x = x * 10 + ch - ‘0‘, ch = getchar();
 15     if(c == ‘-‘)x = -x;
 16 }
 17
 18 const int INF = 0x3f3f3f3f;
 19 const int MAXN = 800 + 10;
 20
 21 int n,cost[MAXN];
 22
 23 struct Edge
 24 {
 25     int u,v,next;
 26     Edge(int _u, int _v, int _next){u = _u;v = _v;next = _next;}
 27     Edge(){}
 28 }edge[MAXN << 1];
 29
 30 int head[MAXN],cnt;
 31
 32 inline void insert(int a, int b)
 33 {
 34     edge[++cnt] = Edge(a,b,head[a]);
 35     head[a] = cnt;
 36 }
 37
 38 int fa[MAXN], dp[MAXN][3];
 39 /*
 40 dp[i][0]表示i放警卫的最小费用
 41 dp[i][1]表示i被儿子看到的最小费用
 42 dp[i][2]表示i被父亲看到的最小费用
 43
 44 dp[i][0] = Σmin(dp[son[i]][2], dp[son[i]][0],dp[son[i][1]) + cost[i]
 45 dp[i][1] = Σmin(dp[son[i]][0], dp[son[i]][1]) + dp[j][0] j从son[i]中除去
 46 dp[i][2] = Σmin(dp[son[i]][1], dp[son[i]][2])
 47 */
 48
 49 void dfs(int u)
 50 {
 51     if(!u)return;
 52     register int num = 0, v, cnt, tmp;//先更新0 2
 53     for(register int pos = head[u];pos;pos = edge[pos].next)
 54     {
 55         v = edge[pos].v;
 56         if(v == fa[u])continue;
 57         fa[v] = u;
 58         ++ num;
 59         dfs(v);
 60         dp[u][0] += min(dp[v][2], min(dp[v][0], dp[v][1]));
 61         dp[u][2] += min(dp[v][1], dp[v][0]);
 62     }
 63     if(!num)
 64     {
 65         dp[u][0] = cost[u];
 66         dp[u][1] = INF;
 67         dp[u][2] = 0;
 68         return;
 69     }
 70     dp[u][0] += cost[u];
 71     dp[u][1] = INF;
 72     for(register int i = 1;i <= num;++ i)
 73     {
 74         cnt = 1;
 75         tmp = 0;
 76         for(register int pos = head[u];pos;pos = edge[pos].next, ++ cnt)
 77         {
 78             v = edge[pos].v;
 79             if(v == fa[u])
 80             {
 81                 -- cnt;
 82                 continue;
 83             }
 84             if(cnt == i)tmp += dp[v][0];
 85             else tmp += min(dp[v][0], dp[v][1]);
 86         }
 87         dp[u][1] = min(dp[u][1], tmp);
 88     }
 89 }
 90
 91 int main()
 92 {
 93     read(n);
 94     register int root, tmp1,tmp2;
 95     for(register int i = 1;i <= n;++ i)
 96     {
 97         read(root),read(cost[root]),read(tmp1);
 98         for(register int j = 1;j <= tmp1;++ j)
 99         {
100             read(tmp2);
101             insert(root, tmp2),insert(tmp2, root);
102         }
103     }
104     dfs(root);
105     printf("%d", min(dp[root][0], dp[root][1]));
106     return 0;
107 }

NKOJ

时间: 2024-12-26 09:47:45

NKOJ1472 警卫安排的相关文章

警卫安排(dp好题)

警卫安排(guard)[题目描述]一个重要的基地被分为 n 个连通的区域.出于某种神秘的原因,这些区域以一个区域为核心,呈一颗树形分布.在每个区域安排警卫所需要的费用是不同的,而每个区域的警卫都可以望见其相邻的区域,只要一个区域被一个警卫望见或者是安排有警卫,这个区域就是安全的.你的任务是:在确保所有区域都是安全的情况下,找到安排警卫的最小费用.[输入格式]第一行 n,表示树中结点的数目.接下来的 n 行描述了n 个区域的信息,每一行包含的整数依次为:区域的标号i(0<i<=n),在区域i 安

树型动态规划练习总结

类型一.多叉树转二叉树进行资源分配 例如: * 例1. 选课:每门课可能有一门先选课,即某些课必须在另外的某节课被选之后才能选,每门课能得的学分不同,求最大学分. * 例2. 通向自由的钥匙:可以从一个房间通向另外多个房间,通过每个房间所需的花费不同,得到的价值也不同,用最小花费获得最大价值. 这种题目的特点是需要在多叉树上进行资源的分配,对不同的子树分配不同的资源,以求最大价值.可以直接在多叉树上用背包的方式求解,但是更常用的方法是用左孩子右兄弟表示法转化为二叉树. 转化之后的通用状态转移方程

动态规划 List

1. LCS 最长公共子序列 /* LCS * Au: GG */ #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <ctime> #include <iostream> #include <algorithm> using namespace std; const int N = 1005; int n,

【题解】警位安排( 树形 DP)

[题目描述]一个重要的基地被分成了 n 个连通的区域 , 出于某种原因 , 这个基地以某一个区域为核心,呈一树形分布.在每个区域里安排警卫的费用是不同的,而每个区域的警卫都可以望见其相邻的区域 .如果一个区域有警卫或是被相邻区域的警卫望见 , 那它就是安全的 , 你的任务是 : 在确保所有的区域安全的状态下,使总费用最小.[输入格式]第一行 n ,表示树中结点的数目.接下来 n 行,每行依次是:区域的编号:在此安排警卫的费用:它的子结点的个数 m ,然后往后 m 个数,为它的子结点编号.[输出格

九度oj 题目1499:项目安排

题目描述: 小明每天都在开源社区上做项目,假设每天他都有很多项目可以选,其中每个项目都有一个开始时间和截止时间,假设做完每个项目后,拿到报酬都是不同的.由于小明马上就要硕士毕业了,面临着买房.买车.给女友买各种包包的鸭梨,但是他的钱包却空空如也,他需要足够的money来充实钱包.万能的网友麻烦你来帮帮小明,如何在最短时间内安排自己手中的项目才能保证赚钱最多(注意:做项目的时候,项目不能并行,即两个项目之间不能有时间重叠,但是一个项目刚结束,就可以立即做另一个项目,即项目起止时间点可以重叠). 输

BZOJ1725: [Usaco2006 Nov]Corn Fields牧场的安排

1725: [Usaco2006 Nov]Corn Fields牧场的安排 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 400  Solved: 290[Submit][Status] Description Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地.FJ打算在牧场上的某几格土地里种上美味的草,供他的奶牛们享用.遗憾的是,有些土地相当的贫

NOJ 1163 活动安排问题 [动态规划]

活动安排问题 时间限制(普通/Java) : 3000 MS/ 9000 MS 运行内存限制 : 65536 KByte总提交 : 202            测试通过 : 55 比赛描述 设有n个活动的集合E={1,2,--,n},其中每个活动都要求使用同一资源,如演讲会场等,而在同一时间内只有一个活动能使用这一资源.每个活动i都有一个要求使用该资源的起始时间si和一个结束时间fi,且si<fi.如果选择了活动i,则它在时间区间[si,fi]内占用资源.若区间[si,fi]与区间[sj,fj

洛谷P1160 队列安排 链表

洛谷P1160 队列安排   链表 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <cstdlib> 5 #include <string> 6 #include <algorithm> 7 #include <iomanip> 8 #include <iostream> 9 using namespace std

关于计应151/152《软件工程》课程实践的安排

通过前一阶段的准备,同学们已经掌握了软件开发流程的相关知识,尽管部分知识有待后续课程解决,但已经具备开始实践的必要知识,因此,从下周一开始,我们的课程实践项目正式开始.具体安排如下: 1.整个开发活动以小组展开,在每一周结束时,小组要提交经过小组实践行动形成的文档,文档内容由我在班级博客上发布,并通过小组长的博客发布,标题格式为:计应XX班第X小组XXX(文档内容标题).文档的具体书写格式和小组的活动方式请参考教材有关章节的内容,这些我会在每次小组作业安排时提示. 2.每个小组成员,根据自己在参