小美拿到了一棵树,每个节点有一个权值。初始每个节点都是白色。
小美有若干次操作,每次操作可以选择两个相邻的节点,如果它们都是白色且权值的乘积是完全平方数,小美就可以把这两个节点同时染红。
小美想知道,自己最多可以染红多少个节点?
第一行输入一个正整数,代表节点的数量。
第二行输入个正整数
,代表每个节点的权值。
接下来的行,每行输入两个正整数
,代表节点
和节点
有一条边连接。
输出一个整数,表示最多可以染红的节点数量。
3 3 3 12 1 2 2 3
2
可以染红第二个和第三个节点。请注意,此时不能再染红第一个和第二个节点,因为第二个节点已经被染红。因此,最多染红 2 个节点。
这道题是树形DP类型:
dp[u][0]
:不染色节点u的情况下,染色节点数最大值; dp[u][1]
:染色节点u的情况下,染色节点数最大值。 然后是状态转移方程:
dp[u][0] += max(dp[i][0], dp[i][1])
,其中i和u在一个图中。不染色u的情况下,染色节点数最大值为它周围子节点的染色节点数最大值之和。 dp[u][1] = max(dp[u][1], dp[u][0] - max(dp[i][0], dp[i][1]) + dp[i][0] + 2)
,其中i和u在一个图中。染色u的情况下,染色节点数最大值需要好好解释。由于题中限制若当前节点染色,那么它相邻的节点只能有一个染色,因此我们需要选择一个相邻节点,使得染色节点数最大。接下来是计算,在节点U不染色且节点I不染色(dp[u][0] - max(dp[i][0], dp[i][1]) + dp[i][0]
)的情况下,将两个节点都染色(+2
)。 代码如下:
#include <iostream> #include <vector> #include <list> #include <cmath> using namespace std; struct Graph { vector<int> value; vector<list<int>> g; Graph(int n) { value.resize(n + 1); g.resize(n + 1); } }; int main() { int n; cin >> n; Graph graph(n); for (int i = 1; i <= n; ++i) { cin >> graph.value[i]; } for (int i = 0; i < n - 1; ++i) { int from, to; cin >> from >> to; graph.g[from].push_back(to); graph.g[to].push_back(from); } // 树形DP: // dp[u][0]: 不染红u情况下, 染红节点数最大值 // dp[u][0] = sum(max(dp[i][0], dp[i][1]), ...), 其中i和u在一个图中 // dp[u][1]: 染红u情况下, 染红节点数最大值 // dp[u][1] = max(dp[u][0] - max(dp[i][0], dp[i][1]) + dp[i][0] + 2), 其中i和u在一个图中 // U不染色 且 I不染色的情况下, 让U和I染色 vector<vector<int>> dp(n + 1, vector<int>(2)); auto DFS = [&](auto&& DFS, int u, int parent) -> void { // 先求dp[u][0] for (int i : graph.g[u]) { // 防止重复求值 if (parent == i) { continue; } DFS(DFS, i, u); dp[u][0] += max(dp[i][0], dp[i][1]); } // 再求dp[u][1] for (int i : graph.g[u]) { // 防止重复求值 if (parent == i) { continue; } int root = static_cast<int>(sqrt(graph.value[i] * graph.value[u])); if (root * root == graph.value[i] * graph.value[u]) { dp[u][1] = max(dp[u][1], dp[u][0] - max(dp[i][0], dp[i][1]) + dp[i][0] + 2); } } }; DFS(DFS, 1, 0); cout << max(dp[1][0], dp[1][1]); } // 64 位输出请用 printf("%lld")
在代码实现中,需要注意的是将子节点和父节点进行比较,避免进行重复计算导致超时,或者结果错误。