首先不难发现,确定了根以后答案是固定的。
设 \(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;
}
标签:sz,int,sum,sol,son,fa,CF1187E,为根
From: https://www.cnblogs.com/wyyqwq/p/18412893