1. 程式人生 > 實用技巧 >Codeforces Round #627 (Div. 3) F. Maximum White Subtree

Codeforces Round #627 (Div. 3) F. Maximum White Subtree

題目連結:https://codeforc.es/contest/1324/problem/F

題意:給定一棵樹,每個點 為1的時白色點,為0的是黑色點,問每一個點 包含該點在內的子樹的最大的 cnt白-cnt黑為多少

思路:樹形dp 用上換根法, 首先以1為根跑一遍dfs 求出 所有的點的子樹的最大值的, 此時只有1的值是確定的最大的,其他的點都是隻有子樹是最大的,上面的部分還沒有計算

然後再跑一遍dfs 開始換根 每一個點,要麼以子樹的為最大的,要麼是以除子樹之外的上部為最大的,要麼是子樹加上上部為最大的

每次跑的時候,上面的根已經處理好了,所以跑一遍就可以得到所有的點的答案 只需討論一下 根的dp[u] 內有無包含cnt[v]就可以了

cnt[v]>0 肯定對根由貢獻,小於0肯定之前沒被加入到根的貢獻中

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define pb push_back
 5 const int maxn =2e5+10;
 6 const int mod=1e9+7;
 7 int a[maxn];
 8 int cnt[maxn];
 9 int dp[maxn];
10 vector<int>E[maxn];
11 
12 
13 
14 void dfs(int u,int
fa) 15 { 16 cnt[u]=a[u]; 17 for(auto &v:E[u]) 18 { 19 if(v==fa) 20 continue; 21 dfs(v,u); 22 cnt[u]+=max(0,cnt[v]); 23 24 } 25 } 26 27 void dfs2(int u,int fa) 28 { 29 for(auto &v:E[u]) 30 { 31 if(v==fa) 32 continue
; 33 if(cnt[v]>=0) 34 { 35 dp[v]=cnt[v]+max(0,dp[u]-cnt[v]); 36 } 37 else 38 { 39 dp[v]=cnt[v]+max(0,dp[u]); 40 } 41 dfs2(v,u); 42 } 43 } 44 45 int main() 46 { 47 ios::sync_with_stdio(false); 48 cin.tie(0); 49 int n; 50 cin>>n; 51 for(int i=1;i<=n;i++) 52 { 53 cin>>a[i]; 54 if(!a[i]) 55 a[i]=-1; 56 } 57 for(int i=1;i<n;i++) 58 { 59 int u,v; 60 cin>>u>>v; 61 E[u].pb(v); 62 E[v].pb(u); 63 } 64 dfs(1,0); 65 dp[1]=cnt[1]; 66 dfs2(1,0); 67 for(int i=1;i<=n;i++) 68 { 69 cout<<dp[i]<<" "; 70 } 71 72 73 74 75 76 77 }
View Code