D. The Omnipotent Monster Killer
You, the monster killer, want to kill a group of monsters. The monsters are on a tree with $n$ vertices. On vertex with number $i$ ($1\le i\le n$), there is a monster with $a_i$ attack points. You want to battle with monsters for $10^{100}$ rounds.
In each round, the following happens in order:
- All living monsters attack you. Your health decreases by the sum of attack points of all living monsters.
- You select some (possibly all or none) monsters and kill them. After being killed, the monster will not be able to do any attacks in the future.
There is a restriction: in one round, you cannot kill two monsters that are directly connected by an edge.
If you choose what monsters to attack optimally, what is the smallest health decrement you can have after all rounds?
Input
Each test contains multiple test cases. The first line contains the number of test cases $t$ ($1 \le t \le 10^4$). Description of the test cases follows.
The first line of each test case contains an integer $n$ ($1\le n\le 3\cdot 10^5$).
The second line of each test case contains $n$ integers $a_1,\ldots,a_n$ ($1\le a_i\le 10^{12}$).
The following $n-1$ lines each contain two integers $x,y$ ($1\le x,y\le n$), denoting an edge on the tree connecting vertex $x$ and $y$.
It is guaranteed that the sum of $n$ over all test cases does not exceed $3\cdot 10^5$.
Output
For each test case, print one integer: the minimum possible health decrement.
Example
input
3
1
1000000000000
5
47 15 32 29 23
1 2
1 3
2 4
2 5
7
8 10 2 3 5 7 4
1 2
1 4
3 2
5 3
6 2
7 5
output
1000000000000
193
57
Note
In the first test case, an optimal sequence of operations would be:
- In the first round: first, receive the attack from the monster on vertex $1$, so your health decreases by $10^{12}$. Then kill the monster on vertex $1$.
- In the second round to the $10^{100}$-th round: all monsters have been killed, so nothing happens.
The total health decrement is $10^{12}$.
In the second test case, an optimal sequence of operations would be:
- In the first round: first, receive the attack from the monster on vertex $1,2,3,4,5$, so your health decreases by $47+15+32+29+23=146$. Then kill the monsters on vertex $1,4,5$.
- In the second round: first, receive the attack from the monster on vertex $2,3$, so your health decreases by $15+32=47$. Then kill the monsters on vertex $2,3$.
- In the third round to the $10^{100}$-th round: all monsters have been killed, so nothing happens.
The total health decrement is $193$.
In the third test case, an optimal sequence of operations would be:
- In the first round: first, receive the attack from the monster on vertex $1,2,3,4,5,6,7$, so your health decreases by $8+10+2+3+5+7+4=39$. Then kill the monsters on vertex $1,3,6,7$.
- In the second round: first, receive the attack from the monster on vertex $2,4,5$, so your health decreases by $10+3+5=18$. Then kill the monsters on vertex $2,4,5$.
- In the third round to the $10^{100}$-th round: all monsters have been killed, so nothing happens.
The total health decrement is $57$.
解题思路
不猜的话很难想到做法,就是最多操作 $O( \log n )$ 轮就能把所有怪物消灭。在这基础上就可以 dp 求解答案了。
为了方便这里固定节点 $1$ 为树根。定义 $f(u,i)$ 表示消灭以 $u$ 为根的子树且 $u$ 在第 $i$ 轮被消灭所造成的最小代价,状态转移方程就是 $f(u,i) = i \cdot a_u + \sum\limits_{v \in \text{son}(u)} \min\limits_{j \ne i} \left\{ f(v,j) \right\}$。其中为了方便这里定义 $i$ 和 $j$ 的取值范围是 $1 \sim 20$(至少取到 $19$)。整个 dp 的时间复杂度是 $O(n \log^2{n})$。
在进行状态转移时,如果提前预处理出 $l_i = \min\limits_{1 \leq j \leq i} \{ f(u,i) \}$ 和 $r_i = \min\limits_{i \leq j \leq 20} \{ f(u,i) \}$,那么状态转移方程就变成 $f(u,i) = i \cdot a_u + \sum\limits_{v \in \text{son}(u)} \min\left\{ l_{i-1}, r_{i+1} \right\}$,时间复杂度降到 $O(n \log{n})$。
最后大概解释一下官方题解中关于最多操作 $\lfloor \log{n} \rfloor + 1$ 轮就能把所有怪物消灭的证明。首先有一个贪心的结论,定义 $b_u$ 表示在最优解中节点 $u$ 是在哪轮被消灭的,假设已知其每个儿子 $v$ 的 $b_v$,那么一定有 $b_u = \underset{v \in \text{son}(u)}{\mathrm{mex}}\{b_v\}$。在保证 $b_u \ne b_v$ 的前提下,当然是希望节点 $u$ 越早被消灭。
现在假设节点 $u$ 的 $b_u = x$ 最大,并将 $u$ 定为整棵树的根节点,由上面的结论知道 $u$ 的所有儿子的 $b_v$ 必定包含了 $1 \sim x-1$ 的所有取值。定义 $f(x)$ 表示根节点在第 $x$ 轮被消灭的树中,至少包含的节点数量。那么有 $f(x) \geq 1 + \sum\limits_{i=1}^{x-1}{f(i)} = 2^{x-2}\left(1 + f(1)\right) = 2^{x-1}$。$f(x)$ 最大取 $3 \cdot 10^{5}$,因此反推得到 $x \leq \lfloor \log{3 \cdot 10^{5}} \rfloor + 1 = 19$。
AC 代码如下,时间复杂度为 $O(n \log{n})$:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 3e5 + 5, M = N * 2;
LL a[N];
int h[N], e[M], ne[M], idx;
LL f[N][25], l[25], r[25];
void add(int u, int v) {
e[idx] = v, ne[idx] = h[u], h[u] = idx++;
}
void dfs(int u, int p) {
for (int i = 1; i <= 20; i++) {
f[u][i] = i * a[u];
}
for (int i = h[u]; i != -1; i = ne[i]) {
int v = e[i];
if (v == p) continue;
dfs(v, u);
l[0] = r[21] = 1e18;
for (int i = 1; i <= 20; i++) {
l[i] = min(l[i - 1], f[v][i]);
}
for (int i = 20; i; i--) {
r[i] = min(r[i + 1], f[v][i]);
}
for (int i = 1; i <= 20; i++) {
f[u][i] += min(l[i - 1], r[i + 1]);
}
}
}
void solve() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%lld", a + i);
}
idx = 0;
memset(h, -1, n + 1 << 2);
for (int i = 0; i < n - 1; i++) {
int u, v;
scanf("%d %d", &u, &v);
add(u, v), add(v, u);
}
dfs(1, 0);
LL ret = 1e18;
for (int i = 1; i <= 20; i++) {
ret = min(ret, f[1][i]);
}
printf("%lld\n", ret);
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}
参考资料
Editorial of Codeforces Round 958 (Div. 2):https://codeforces.com/blog/entry/131567
标签:10,Omnipotent,Killer,vertex,monsters,health,first,round,Monster From: https://www.cnblogs.com/onlyblues/p/18306116