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 }
View Code

 

posted @ 2020-10-23 22:10  canwinfor  阅读(98)  评论(0)    收藏  举报