4557: [JLoi2016]侦察守卫 树形dp

一道好题,但也是一道水题。 可怜yyl蒟蒻看了别人怎么开数组后还是不会写。 orz各位大神。

接下来上大神的题解(注意不是我的):

比较简单的一个DP
f[i][j]表示节点为i的子树向下j层以下需要被覆盖的节点已经被覆盖了的答案
g[i][j]表示节点为i的子树,子树内需要被覆盖的几点已经被覆盖了,还可以向上覆盖j层的答案
f[i][0]=g[i][0]
然后正着反着取两遍最小值即可

 

接着yy应该可以出来了。感觉不难。就是想不到……………………。too young too simple

 1 #include<cstdio>
 2 #include<iostream>
 3 #define rep(i,j,k) for(register int i = j; i <= k; i++)
 4 #define dow(i,j,k) for(register int i = j; i >= k; i--)
 5 #define ez(i,j) for(edge*i = head[j]; i; i=i->next)
 6 #define maxn 502333
 7 #define inf 0x7fffffff
 8 using namespace std;
 9  
10 inline int read() {
11     int s = 0, t =1; char c = getchar();
12     while( !isdigit(c) ) { if( c == '-' ) t = -1; c = getchar(); }
13     while( isdigit(c) ) s = s * 10 + c - 48, c = getchar();
14     return s * t;
15 }
16  
17 struct edge{ int to; edge*next; } e[maxn<<1], *pt = e, *head[maxn];
18 inline void add(int x,int y) { pt->to = y, pt->next = head[x], head[x] = pt++; pt->to = x, pt->next = head[y], head[y] = pt++; }
19 int f[maxn][25], g[maxn][25], w[maxn], d; bool ned[maxn][25];
20  
21 #define to i->to
22 inline void dp(int x,int fa) {
23     bool out = 0;
24     ez(i,x) if( to != fa ) { dp(to,x), out = 1; }
25     rep(j,1,d) {
26         ned[x][j] |= ned[x][j-1];
27         if( !ned[x][j] ) ez(i,x) if( to != fa && ned[to][j-1] ) { ned[x][j] |= 1; break; }
28     }
29     if( !out ) {
30         rep(i,1,d) g[x][i] = w[x];
31         if( ned[x][0] ) f[x][0] = g[x][0] = w[x]; else f[x][0] = g[x][0] = 0;
32         rep(i,1,d) f[x][i] = 0;
33         return;
34     }
35     rep(j,1,d) {
36         f[x][j] = 0;
37         ez(i,x) if( to != fa ) f[x][j] += f[to][j-1]; 
38     }
39     g[x][d] = 0;
40     ez(i,x) if( to != fa ) g[x][d] += f[to][d];
41     g[x][d] += w[x];
42     dow(j,d-1,0) {
43         int sum = 0;
44         ez(i,x) if( to != fa ) sum += f[to][j];
45         g[x][j] = inf;
46         ez(i,x) if( to != fa ) g[x][j] = min(g[x][j],g[to][j+1]+sum-f[to][j]);
47     }
48     dow(i,d,1) g[x][i-1] = min(g[x][i-1],g[x][i]);
49     f[x][0] = g[x][0];
50     rep(i,1,d) f[x][i] = min(f[x][i],f[x][i-1]);
51     dow(i,d-1,0) if( !ned[x][i] ) f[x][i] = min(f[x][i+1], f[x][i]);
52     g[x][0] = f[x][0];
53 }
54  
55 int main() {
56     int n = read(); d = read();
57     rep(i,1,n) w[i] = read(); 
58     int m = read();
59     rep(i,1,m) ned[read()][0] = 1;
60     rep(i,1,n-1) add(read(),read());
61     dp(1,0);
62     printf("%d\n", f[1][0]);
63     return 0;
64 }

 

posted on 2016-05-05 21:15  83131  阅读(235)  评论(0编辑  收藏  举报

导航