CF1187E sol

你说得太对辣發表於2024-09-13

首先不難發現,確定了根以後答案是固定的。

\(sz_i\) 表示以 1 為根的樹中,以 1 為根的子樹大小;\(f_i\) 表示以 1 為根的樹中,以 \(i\) 為根的子樹得到的最大權值,可以得到轉移

\[f_u = sz_u + \sum_{v \in son_u} f_v \]

然後設 \(g_v\) 表示先選 \(v\) 的最大權值,\(v\) 的父親為 \(u\)

\[g_1 = f_1 \]

\[g_j = n + (n - sz_j) + \sum_{v \in j} f_v + \sum_{v \in son_i | v \neq j} f_v \]

\[g_j = 2n - sz_j + f_j - sz_j + \sum_{v \in son_i | v \neq j} f_v \]

\[g_j = 2n - 2sz_j + \sum_{v \in son_i} f_v \]

\[g_j = f_i + n - 2sz_j \]

dp 即可。

#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N = 1e6 + 7;
vector<int> g[N];
int sz[N], ans[N];
int f[N], ff[N];
int n;
void dfs1(int u, int fa) {
    sz[u] = 1;
    for(int v : g[u]) {
        if(v == fa) continue;
        dfs1(v, u);
        sz[u] += sz[v];
        f[u] += f[v];
    }
    f[u] += sz[u];
}
void dfs2(int u, int fa) {
    for(int v : g[u]) {
        if(v == fa) continue;
        ff[v] = n + ff[u] - 2 * sz[v];
        dfs2(v, u);
    }
}
signed main() {
    
    cin >> n;
    for(int i = 1; i < n; i ++) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v), g[v].push_back(u);
    }
    
    dfs1(1, 0);
    ff[1] = f[1];
    dfs2(1, 0);
    int ans = -1;
    for(int i = 1; i <= n; i ++) ans = max(ans, ff[i]);
    cout << ans << endl;
    return 0;
}