CF-1187 E. Tree Painting (换根DP)

题目链接

题意:给你一棵树,起初,每个节点都是白色的,现在要把树染黑,每次选择一个节点,可以获得与该点连通的白色节点的总数的得分,然后再将该节点染黑。
选择节点的要求,第一次可以以任意选择,后面就只能选择与黑色节点相连的白色节点

代码:

#include <bits/stdc++.h>
#define debug(x) cout<<#x<<"="<<x<<endl;
#define debug2(x, y) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<endl;
#define debug3(x, y, z) cout<<#x<<"="<<x<<" "<<#y<<"="<<y<<" "<<#z<<"="<<z<<endl;
const int maxn = 2e5+50;
using namespace std;
typedef long long ll;

vector <int> maps[maxn];
int n;
ll sz[maxn], dp[maxn];

void dfs1(int u, int fa){
    sz[u] = 0;
    for(int i=0, len=maps[u].size(); i<len; i++){
        int v = maps[u][i];
        if(v != fa){
            dfs1(v, u);
            sz[u] += sz[v];
            dp[u] += dp[v];
        }
    }
    sz[u]++;
    dp[u] += sz[u];
}
ll ans;
void dfs2(int u, int fa){
    for(int i=0, len=maps[u].size(); i<len; i++){
        int v = maps[u][i];
        if(v != fa){
            dp[v] =  dp[u] + n - 2*sz[v];   //简单推一推,就能推出来
            ans = max(ans, dp[v]);
            dfs2(v, u);
        }
    }
}

int main()
{
    scanf("%d", &n);
    for(int i=1, a, b; i<n; i++){
        scanf("%d%d", &a, &b);
        maps[a].push_back(b);
        maps[b].push_back(a);
    }
    dfs1(1, 1);
    ans = dp[1];
    dfs2(1, 1);
    printf("%lld
", ans);
    return 0;
}

原文地址:https://www.cnblogs.com/jizhihong/p/13337333.html