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 }
————————————————