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;
}

posted @ 2026-05-21 17:32  風月華  阅读(6)  评论(0)    收藏  举报