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

浙公网安备 33010602011771号