Codeforces Round #168 (Div. 1) B. Zero Tree

题目链接: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 }
View Code

 

posted @ 2021-03-15 12:12  canwinfor  阅读(58)  评论(0)    收藏  举报