题解 CF1187E 【Tree Painting】

大意

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

思路

那么我们很容易意识到,起关键作用的就是选择了那个根节点。设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】

上一篇:Ajax中post请求和get请求的区别


下一篇:火山引擎MARS-APM Plus x 飞书 |降低线上OOM,提高App性能稳定性