Tree Painting - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
Solution
容易得出结论:可选择的只有第一个染色点,且不妨将该点视作根结点。该点确定后,本题答案也就确定了为所有子树的大小之和。现在要求的是如何选择根结点,使得答案最大。
设 为以 为根的子树对答案的贡献。当 为树根时,答案为 。 为 为树根时,以 为根的子树的大小。不妨一开始以 为第一个染色点,然后进行换根 dp,按 dfs 序选择新的根。设 为 的儿子,则可知
又因为
和
联立三式得到
这个例子是把根从 换到子结点 。同理,所有的 均可按照同样的方法由父结点的 得到。最大的 为所求。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 2e5 + 10;
ll n, f[N], ans, siz[N];
vector<ll> g[N];
void dfs(ll u, ll fa)
{
siz[u] = 1;
for (auto v : g[u]) {
if (v == fa) continue;
dfs(v, u);
siz[u] += siz[v];
f[u] += f[v];
}
f[u] += siz[u];
}
void dp(ll u, ll fa)
{
ans = max(ans, f[u]);
for (int v : g[u]) {
if (v == fa) continue;
f[v] = n + f[u] - 2 * siz[v];
dp(v, u);
}
}
int main()
{
scanf("%lld", &n);
for (int i = 1; i < n; i++) {
ll u, v;
scanf("%lld%lld", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1, 0); ans = f[1]; dp(1, 0);
printf("%lld", ans);
return 0;
}