码迷,mamicode.com
首页 > 其他好文 > 详细

vijos1144小胖守皇宫

时间:2018-06-30 14:40:06      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:block   end   最小点覆盖   span   std   表示   n+1   ==   起点   

细节很精妙

描述

huyichen世子事件后,xuzhenyi成了皇上特聘的御前一品侍卫。

皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫殿安排看守所需的费用不同。

可是xuzhenyi手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。

帮助xuzhenyi布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。

格式

输入格式

输入文件中数据表示一棵树,描述如下:

第1行 n,表示树中结点的数目。

第2行至第n+1n+1行,每行描述每个宫殿结点信息,依次为:该宫殿结点标号i(0<i \le n0<i≤n),在该宫殿安置侍卫所需的经费k,该点的儿子数m,接下来m个数,分别是这个节点的m个儿子的标号r_1, r_2, \cdots, r_mr1?,r2?,?,rm?。

对于一个n(0 < n \le 15000<n≤1500)个结点的树,结点标号在1到n之间,且标号不重复。保证经费总和不超过2^31-1231−1。

输出格式

输出文件仅包含一个数,为所求的最少的经费。

题目分析

有些细节处理真的是非常精妙。

分析详见初涉树形dp【权最小点覆盖】vijos1144皇宫看守

 1 #include<bits/stdc++.h>
 2 const int maxn = 2003;
 3 
 4 int f[maxn][3],a[maxn],n,rt;
 5 int head[maxn],nxt[maxn<<1],edges[maxn<<1],edgeTot;
 6 bool vis[maxn];
 7 
 8 int read()
 9 {
10     char ch = getchar();
11     int num = 0;
12     bool fl = 0;
13     for (; !isdigit(ch); ch = getchar())
14         if (ch==-) fl = 1;
15     for (; isdigit(ch); ch = getchar())
16         num = (num<<1)+(num<<3)+ch-48;
17     if (fl) num = -num;
18     return num;
19 }
20 inline int min(int a, int b){return a<b?a:b;}
21 inline int min(int a, int b, int c){int t=min(a,b);return t<c?t:c;}
22 void addedge(int u, int v)
23 {
24     edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
25     vis[v] = 1;
26 }
27 void dfs(int now)
28 {
29     int delta = 2e9;
30     for (int i=head[now]; i!=-1; i=nxt[i])
31     {
32         int v = edges[i];
33         dfs(v);
34         f[now][0] += min(f[v][1], f[v][2]);
35         f[now][1] += min(f[v][1], f[v][2]);
36         delta = min(f[v][2]-f[v][1], delta);
37         f[now][2] += min(f[v][0], f[v][1], f[v][2]);
38     }
39     delta = std::max(delta, 0);
40     f[now][1] += delta;
41 }
42 int main()
43 {
44     memset(head, -1, sizeof head);
45     n = read();
46     for (int i=1; i<=n; i++)
47     {
48         int p = read(), k;
49         f[p][2] = a[p] = read(), k = read();
50         while (k--) addedge(p, read());
51     }
52     rt = 1;
53     while (vis[rt]) rt++;
54     dfs(rt);
55     printf("%d\n",min(f[rt][1], f[rt][2]));
56     return 0;
57 }

 

 

 

END

vijos1144小胖守皇宫

标签:block   end   最小点覆盖   span   std   表示   n+1   ==   起点   

原文地址:https://www.cnblogs.com/antiquality/p/9246654.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!