题目链接:http://codeforces.com/problemset/problem/274/B
题意:选择包含节点1的一些相连的点,每次可以进行加1和减1的操作,问最少操作多少次全部节点的权值为0
思路:考虑任意一个节点,如果要更新这个节点的子节点的话,必须要通过这个唯一的父节点才能更新
所以dp[u][0/1] 表示通过u这个点的最少加法次数 和最少减法次数, 所以是dp[u][0]=max(dp[v][0]) 用最大的子节点
才能使得次数最少,然后还要加上当前的a[u] 即可
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 pb push_back 8 #define pi pair<int,int> 9 #define fi first 10 #define sc second 11 12 int n; 13 vector<int>E[maxn]; 14 ll a[maxn]; 15 ll dp[maxn][2]; 16 17 void dfs(int u,int fa) 18 { 19 20 for(auto &v:E[u]) 21 { 22 if(v==fa) continue; 23 dfs(v,u); 24 dp[u][0]=max(dp[u][0],dp[v][0]); 25 dp[u][1]=max(dp[u][1],dp[v][1]); 26 } 27 a[u]+=dp[u][0]-dp[u][1]; 28 if(a[u]>0) dp[u][1]+=a[u]; 29 else dp[u][0]+=abs(a[u]); 30 } 31 32 int main() 33 { 34 ios::sync_with_stdio(0); 35 cin.tie(0); 36 cin>>n; 37 for(int i=1;i<n;i++) 38 { 39 int x,y; 40 cin>>x>>y; 41 E[x].pb(y); 42 E[y].pb(x); 43 } 44 for(int i=1;i<=n;i++) cin>>a[i]; 45 dfs(1,0); 46 cout<<dp[1][0]+dp[1][1]<<‘\n‘; 47 48 49 50 51 52 }
Codeforces Round #168 (Div. 1) B. Zero Tree
原文:https://www.cnblogs.com/winfor/p/14536843.html