BZOJ1722 [Usaco2006 Mar] Milk Team Select 产奶比赛

直接树形dp就好了恩

令$f[i][j][t]$表示以$i$为根的子树,选出来的点存在$j$对父子关系,$t$表示$i$这个点选或者没选,的最大产奶值

分类讨论自己和儿子分别有没有选,然后转移一下就好了。。。恩,详情看代码好了

 1 /**************************************************************
 2     Problem: 1722
 3     User: rausen
 4     Language: C++
 5     Result: Accepted
 6     Time:28 ms
 7     Memory:2808 kb
 8 ****************************************************************/
 9  
10 #include <cstdio>
11 #include <algorithm>
12  
13 using namespace std;
14 const int N = 505;
15 const int inf = 1e9;
16  
17 struct edge {
18     int next, to;
19     edge(int _n = 0, int _t = 0): next(_n), to(_t) {}
20 } e[N];
21  
22 struct tree_node {
23     int v, fa;
24 } tr[N];
25  
26 int n, tar, ans;
27 int first[N], tot;
28 int f[N][N][2];
29  
30 inline void add_edge(int x, int y) {
31     e[++tot] = edge(first[x], y);
32     first[x] = tot;
33 }
34  
35 #define y e[x].to
36 void dfs(int p) {
37     int t1, t2, tmp, i, j, x;
38     static int t[N];
39     f[p][0][0] = 0, f[p][0][1] = tr[p].v;
40     for (i = 1; i < n; ++i)
41         f[p][i][0] = f[p][i][1] = -inf;
42     if (first[p] == 0) return;
43     for (x = first[p]; x; x = e[x].next) {
44         dfs(y);
45         for (t1 = 0; t1 < 2; ++t1) {
46             for (j = 0; j < n; ++j) t[j] = f[p][j][t1];
47             for (t2 = 0; t2 < 2; ++t2) {
48                 tmp = t1 && t2 && p;
49                 for (i = 0; i < n; ++i) if (f[y][i][t2] != -inf)
50                     for(j = n - 1; i + tmp <= j; --j)
51                         if (f[p][j - i - tmp][t1] != -inf)
52                             t[j] = max(t[j], f[p][j - i - tmp][t1] + f[y][i][t2]);
53             }
54             for (j = 0; j < n; ++j) f[p][j][t1] = max(f[p][j][t1], t[j]);
55         }
56     }
57      
58 }
59 #undef y
60  
61 int main() {
62     int i;
63     scanf("%d%d", &n, &tar);
64     for (i = 1; i <= n; ++i) {
65         scanf("%d%d", &tr[i].v, &tr[i].fa);
66         add_edge(tr[i].fa, i);
67     }
68     dfs(0);
69     for (ans = n - 1; ~ans && f[0][ans][0] < tar; --ans);
70     printf("%d
", ans);
71     return 0;
72 }
View Code
By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
原文地址:https://www.cnblogs.com/rausen/p/4461607.html