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 }

 

posted @ 2021-04-08 14:21  acmloser  阅读(38)  评论(0编辑  收藏  举报