换根DP

别问我为什么断断续续的,因为老师Wendaysif的断断续续的

重点来了:还是换根Dp

直接讲例题吧

CF1187E Tree Painting

你打开以后可能是

话不多说,因为多说了也是废话。

解法

一眼 \(DP\) 别问我怎么看出来的,问就是老师拉进了题单里。

如果你选定了一个节点 \(u\) 作为根 ,那么按照规则染完整棵树,总得分就是:

\[\sum_{i = 1}^n sz[i] \]

\(dp_u\) 表示以 \(u\) 为根的子树的答案。

首先,可以从 \(1\) 开始, \(DFS\) 一遍,计算出以 \(1\) 为根时,每个点的子树答案 \(dp_u\) 以及子树大小 \(sz_u\)
目标是根据这里的 \(dp\)\(sz\) 求出以每个点作为根的答案 \(G_u\)
假设当前根是 \(u\) ,我们知道 \(dp_u\) 。这也是以 \(u\) 为根的子树的答案 \(G_u\)
现在我们要把根移到相邻节点 \(v\)。现在想要求 \(G_v\)

自己画个图理解一下。

最后得到

\[G_v = G_u + n - 2 \times sz_v \]

好了,结束

戳我看代码
int n;
vector<int> g[N];
int sz[N], G[N];

void dfs1(int u, int fa) {
	sz[u] = 1;
	for (auto v : g[u]) {
		if (v == fa) continue;
		dfs1(v, u);
		sz[u] += sz[v];
	}
	G[1] += sz[u];
}

void dfs2(int u, int fa) {
	for (auto v : g[u]) {
		if (v == fa) continue;
		G[v] = G[u] + n - 2 * sz[v];
		dfs2(v, u);
	}
}

posted @ 2026-02-06 20:42  OiLight  阅读(23)  评论(0)    收藏  举报