P3047 [USACO12FEB]Nearby Cows G
考察:树形dp
思路:
换根dp,f[i][j][0]表示以i为根的子树中与i距离不超过j的权值和.f[i][j][1]表示以i为起点,往上走距离不超过j的点集合.
易知f[i][j][0] += f[v][j-1][0] 其中f[i][0][0] = w[i]
如果是往上走:f[v][j][1] = f[u][j-1][0]-f[v][j-2][0]+f[u][j-1][1]. 注意初始化f[v][1][1] = w[u]
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 typedef long long LL; 6 const int N = 100010,M = 25; 7 int n,k,w[N],h[N],idx,ans; 8 LL f[N][M][2]; 9 struct Road{ 10 int fr,to,ne; 11 }road[N<<1]; 12 void add(int a,int b) 13 { 14 road[idx].fr = a,road[idx].to = b,road[idx].ne = h[a],h[a] = idx++; 15 } 16 void dfs_up(int u,int fa) 17 { 18 for(int i=h[u];i!=-1;i=road[i].ne) 19 { 20 int v = road[i].to; 21 if(v==fa) continue; 22 f[v][1][1]+=w[u]; 23 for(int j=2;j<=k;j++) 24 f[v][j][1] += f[u][j-1][0]-f[v][j-2][0]+f[u][j-1][1]; 25 dfs_up(v,u); 26 } 27 } 28 void dfs(int u,int fa) 29 { 30 for(int i=h[u];i!=-1;i=road[i].ne) 31 { 32 int v = road[i].to; 33 if(v==fa) continue; 34 dfs(v,u); 35 for(int j=1;j<=k;j++) 36 f[u][j][0] +=f[v][j-1][0]; 37 } 38 for(int i=0;i<=k;i++) f[u][i][0] += w[u]; 39 } 40 int main() 41 { 42 scanf("%d%d",&n,&k); 43 memset(h,-1,sizeof h); 44 for(int i=1;i<n;i++) 45 { 46 int a,b; scanf("%d%d",&a,&b); 47 add(a,b); add(b,a); 48 } 49 for(int i=1;i<=n;i++) scanf("%d",&w[i]); 50 dfs(1,-1); 51 dfs_up(1,-1); 52 for(int i=1;i<=n;i++) 53 printf("%d\n",f[i][k][0]+f[i][k][1]); 54 return 0; 55 }