[USACO12FEB]Nearby Cows G

题目链接:https://www.luogu.com.cn/problem/P3047

思路:首先要求的是树中所有的子节点 那么考虑换根dp  然后考虑如何通过父节点来更新子节点

虽然k很小 但是暴力更新可能会有很多层所以TLE 考虑dp[i][j] 表示距离以i为根节点距离为j的值

所以每次 换根的时候 只需要把 根节点的减去子节点那一边的dp 就可以得到另外一边的贡献

然后回溯的时候记得 把dp复原即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5+10;
 4 const int mod=998244353;
 5 #define ll long long
 6 #define ull unsigned long long
 7 #define pi pair<int,ll>
 8 #define fi first
 9 #define sc second
10 #define pb push_back
11 vector<int>E[maxn];
12 int c[maxn];
13 int n,k;
14 int dp[maxn][30];
15 int sum[maxn];
16 
17 void dfs(int u,int fa)
18 {
19     dp[u][0]=c[u];
20     for(auto &v:E[u])
21     {
22         if(v==fa) continue;
23         dfs(v,u);
24         for(int i=1;i<=k;i++)
25             dp[u][i]+=dp[v][i-1];
26     }
27 }
28 void add(int u,int v,int t)
29 {
30     for(int i=1;i<=k;i++)
31     {
32         if(t) dp[u][i]+=dp[v][i-1];
33         else dp[u][i]-=dp[v][i-1];
34     }
35 }
36 
37 void dfs22(int u,int fa)
38 {
39     for(int i=0;i<=k;i++) sum[u]+=dp[u][i];
40     for(auto &v:E[u])
41     {
42         if(v==fa) continue;
43         add(u,v,0),add(v,u,1);
44         dfs22(v,u);
45         add(v,u,0),add(u,v,1);
46     }
47 }
48 
49 int main()
50 {
51     ios::sync_with_stdio(0);
52     cin.tie(0);
53     cin>>n>>k;
54     for(int i=1;i<n;i++)
55     {
56         int x,y;
57         cin>>x>>y;
58         E[x].pb(y);
59         E[y].pb(x);
60     }
61     for(int i=1;i<=n;i++) cin>>c[i];
62     dfs(1,0);
63     dfs22(1,0);
64     for(int i=1;i<=n;i++) cout<<sum[i]<<'\n';
65 
66 }
View Code

 

posted @ 2021-03-05 16:09  canwinfor  阅读(100)  评论(0)    收藏  举报