码迷,mamicode.com
首页 > 其他好文 > 详细

题解 CF1187E 【Tree Painting】

时间:2021-06-24 18:02:05      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:void   printf   lang   push   cto   def   strong   return   c代码   

大意

给一棵树,初始时结点都为白色,然后你可以选一个点作为根节点,加上这个节点连通的白色节点数,然后把这个点染黑。下面再继续选择与黑节点相连的点,加上白色节点数,染黑。求最大的值。

思路

那么我们很容易意识到,起关键作用的就是选择了那个根节点。设dp[i]为以i为根节点的最大值。则,我们对于一个根节点,如点1,记sum[i]为i节点子树的个数,则

$ dp[1]=sum[1]+sum[2]+...+sum[n] $

那么转移到下一个点,如2号点,有:

$ dp[2]=sum[1]+sum[3]+sum[4]+...+sum[n]+(sum[1]-sum[2]) $

很显然,每次换根后,需要 $ -2*sum[to]+sum[1] $,2次搜索即可

Code

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll son[200005];
ll all,ans;
vector<int>vec[200005];
void dfs1(int now,int fa,int dep){
    all+=dep;
    son[now]=1;
    for(int i=0;i<vec[now].size();i++){
        int to=vec[now][i];
        if(to!=fa){
            dfs1(to,now,dep+1);
            son[now]+=son[to];
        }
    }
}
void dfs2(int now,int fa,ll val){
    ans=max(ans,val);
    for(int i=0;i<vec[now].size();i++){
            int to=vec[now][i];
            if(to!=fa){
                dfs2(to,now,val-2ll*son[to]+son[1]);
            }
        }
}
int main(){
    all=0,ans=0;
    int n,a,b;
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        scanf("%d%d",&a,&b);
        vec[a].push_back(b);
        vec[b].push_back(a);
    }
    dfs1(1,1,1);
    dfs2(1,1,all);
    printf("%lld\n",ans);
    return 0;

}

题解 CF1187E 【Tree Painting】

标签:void   printf   lang   push   cto   def   strong   return   c代码   

原文地址:https://www.cnblogs.com/will1477/p/14925361.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!