Sheriff’s Defense
#树形结构 #树形dp #动态规划
题目描述
The folk hero Robin Hood has been troubling Sheriff of Nottingham greatly. Sheriff knows that Robin Hood is about to attack his camps and he wants to be prepared.
Sheriff of Nottingham built the camps with strategy in mind and thus there are exactly n n n camps numbered from 1 1 1 to n n n and n − 1 n-1 n−1 trails, each connecting two camps. Any camp can be reached from any other camp. Each camp i i i has initially a i a_i ai gold.
As it is now, all camps would be destroyed by Robin. Sheriff can strengthen a camp by subtracting exactly c c c gold from each of its neighboring camps and use it to build better defenses for that camp. Strengthening a camp doesn’t change its gold, only its neighbors’ gold. A camp can have negative gold.
After Robin Hood’s attack, all camps that have been strengthened survive the attack, all others are destroyed.
What’s the maximum gold Sheriff can keep in his surviving camps after Robin Hood’s attack if he strengthens his camps optimally?
Camp a a a is neighboring camp b b b if and only if there exists a trail connecting a a a and b b b. Only strengthened camps count towards the answer, as others are destroyed.
输入格式
The first line contains a single integer t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1≤t≤104) — the number of test cases.
Each test case begins with two integers n n n, c c c ( 1 ≤ n ≤ 2 ⋅ 1 0 5 , 1 ≤ c ≤ 1 0 9 1 \le n \le 2\cdot10^5, 1 \le c \le 10^9 1≤n≤2⋅105,1≤c≤109) — the number of camps and the gold taken from each neighboring camp for strengthening.
The second line of each test case contains n n n integers a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,…,an ( − 1 0 9 ≤ a i ≤ 1 0 9 -10^9 \le a_i \le 10^9 −109≤ai≤109) — the initial gold of each camp.
Then follow n − 1 n-1 n−1 lines, each with integers u u u, v v v ( 1 ≤ u , v ≤ n 1 \le u, v \le n 1≤u,v≤n, u ≠ v u \ne v u=v) — meaning that there is a trail between u u u and v v v.
The sum of n n n over all test cases doesn’t exceed 2 ⋅ 1 0 5 2\cdot10^5 2⋅105.
It is guaranteed that any camp is reachable from any other camp.
输出格式
Output a single integer, the maximum gold Sheriff of Nottingham can keep in his surviving camps after Robin Hood’s attack.
样例 #1
样例输入 #1
5
3 1
2 3 1
1 2
2 3
3 1
3 6 3
1 2
2 3
3 1
-2 -3 -1
1 2
2 3
6 1
5 -4 3 6 7 3
4 1
5 1
3 5
3 6
1 2
8 1
3 5 2 7 8 5 -3 -4
7 3
1 8
4 3
3 5
7 6
8 7
2 1
样例输出 #1
3
8
0
17
26
解题思路
看这种具有依赖关系的树形结构,很容易就想到树形 d p dp dp,显然这题也是
我们设计两个状态 f u , 0 f_{u,0} fu,0和 f u , 1 f_{u,1} fu,1,分别表示当前 u u u节点不选择强化和 u u u节点选择强化的最大贡献。
选择强化当前节点就要使相邻的节点减去 c c c这个贡献,包括其父节点,不过对于父节点的贡献可以等递归回溯到父节点累加为 2 ∗ c 2*c 2∗c,因此转移方程如下:
{ f u , 0 + = max ( f v , 0 , f v , 1 ) f u , 1 + = max ( f v , 0 , f v , 1 − 2 ∗ c ) \begin{cases} f_{u,0} += \max(f_{v,0},f_{v,1}) \\ f_{u,1} += \max(f_{v,0},f_{v,1} - 2*c) \end{cases} {fu,0+=max(fv,0,fv,1)fu,1+=max(fv,0,fv,1−2∗c)
代码
const int N = 2e5 + 10;
void solve() {
int n, c;
std::cin >> n >> c;
std::vector<int>w(n + 1);
for (int i = 1; i <= n; ++i) {
std::cin >> w[i];
}
std::vector<std::vector<int>>e(n + 1);
for (int i = 1; i <= n - 1; ++i) {
int u, v;
std::cin >> u >> v;
e[v].emplace_back(u);
e[u].emplace_back(v);
}
std::vector <std::array<int, 2>> f(n + 1);
auto dfs = [&](auto&& self, int u, int fa)->void {
f[u][0] = 0; f[u][1] = w[u];
for (auto& v : e[u]) {
if (v == fa) continue;
self(self, v, u);
f[u][0] += std::max(f[v][0], f[v][1]);
f[u][1] += std::max(f[v][0], f[v][1] - 2 * c);
}
};
dfs(dfs, 1, -1);
int res = std::max(f[1][0], f[1][1]);
std::cout << res << "\n";
}
signed main() {
std::ios::sync_with_stdio(0);
std::cin.tie(0);
std::cout.tie(0);
int t = 1;
std::cin >> t;
while (t--) {
solve();
}
};