Educational Codeforces Round 67 (Rated for Div. 2) E. Tree Painting ###K ###K //K
题目链接:https://codeforces.ml/contest/1187/problem/E
题意:一开始整棵树上的点都是白的,一开始随意取一个点将其涂黑,然后剩下操作每次要涂已经涂黑的点的相邻点
每次获得的贡献值是所涂的点的整个连通的白色点的数量
思路:并不知道从那个点开始涂才是最优, 那么考虑把所有的点都算一遍,要把树上所有的点都算一遍 不难想到换根dp
第一次dfs求出某一个点的 dp[u] 第二次dfs求出其他点的dp[u]
考虑换根时候的转移,有两种想法 cnt[i]为i的子树个数
第一种: 考虑是 u=1 v=2 要把根换去2 那么dp[2] 和dp[1]不同的就是 损失掉了cnt[2] 然后多出来的是cnt[1] 其他都不变
所以 dp[v]=dp[u]-cnt[v]+(n-cnt[v])=dp[u]-2cnt[v]+n
第二种: 考虑断开1 和2 那么只需要考虑 上半子树1的部分和 下半子树2的部分
即 dp[v]=上+下+n
下的部分即dp[v]-cnt[v] 上的部分为 dp[u]-dp[v]-n+(n-cnt[v]) 即 总的减去下半 减去n 再+上本身的贡献
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=998244353; 7 vector<int>E[maxn]; 8 ll dp[maxn]; 9 ll ans=0; 10 ll cnt[maxn]; 11 int n; 12 13 14 void dfs(int u,int fa) 15 { 16 cnt[u]=1; 17 for(auto &v:E[u]) 18 { 19 if(v==fa) 20 continue; 21 dfs(v,u); 22 cnt[u]+=cnt[v]; 23 dp[u]+=dp[v]; 24 } 25 dp[u]+=cnt[u]; 26 } 27 28 void dfs222(int u,int fa) 29 { 30 for(auto &v:E[u]) 31 { 32 if(v==fa) 33 continue; 34 dp[v]=dp[u]-cnt[v]+n-cnt[v]; 35 ans=max(ans,dp[v]); 36 dfs222(v,u); 37 } 38 } 39 40 int main() 41 { 42 ios::sync_with_stdio(false); 43 cin.tie(0); 44 cin>>n; 45 for(int i=1;i<n;i++) 46 { 47 int x,y; 48 cin>>x>>y; 49 E[x].pb(y); 50 E[y].pb(x); 51 } 52 dfs(1,0); 53 ans=dp[1]; 54 dfs222(1,0); 55 cout<<ans<<'\n'; 56 57 58 59 }

浙公网安备 33010602011771号