CF1187E Tree Painting
跟P3478没什么本质区别吧,难点在于需要解析出来题目隐藏信息。
首先要确定一件事,如果我们定下了第一个染色节点,那么这种情况的答案就确定了。
为啥呢?考虑以这个染色节点为根,那么每个儿子节点之间就已经是独立的了(被根节点隔开),不管你先染哪个儿子,答案都不会变。
顺便我们也就确定了染色方案。也就是确定第一个染色节点之后,从上往下染。染的每一个节点的分数就是这个节点的子树大小。
因此问题转化为了,对于一棵树,求一个节点使得当他为根时,所有节点的子树大小之和最小。
然后就好解决了。设 \(dp_i\) 为以 \(i\) 为根的子树大小之和,预处理出 \(dp_1\)。
\[dp_{to} = dp_s + n - siz_{to} * 2
\]
这个画个图就可以看出来。
#include <bits/stdc++.h>
#define m_p(x, y) make_pair(x, y)
#define pb(x) push_back(x)
#define int long long
#define ull unsigned long long
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define rep_(i, a, b) for(int i = a; i >= b; --i)
using namespace std;
namespace FYH {
constexpr int N = 2e5 + 5;
int ans, n, u, v, dp[N], siz[N];
vector<int> e[N];
void dfs(int s, int fa) {
siz[s] = 1;
for(const int to : e[s]) {
if(to == fa) continue;
dfs(to, s);
siz[s] += siz[to];
}
}
void dfs2(int s, int fa) {
for(const int to : e[s]) {
if(to == fa) continue;
dp[to] = dp[s] + n - siz[to] * 2;
dfs2(to, s);
}
}
void main() {
cin >> n;
rep(i, 1, n - 1) {
cin >> u >> v;
e[u].pb(v);
e[v].pb(u);
}
dfs(1, 0);
rep(i, 1, n) {
dp[1] += siz[i];
}
dfs2(1, 0);
rep(i, 1, n) {
ans = max(ans, dp[i]);
}
cout << ans;
}
}
signed main() {
ios :: sync_with_stdio(0), cin.tie(0);
int t = 1;
//cin >> t;
while(t--) {
FYH :: main();
}
return 0;
}

浙公网安备 33010602011771号