首先不難發現,確定了根以後答案是固定的。
設 \(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;
}