题解:AT_arc083_c [ARC083E] Bichrome Tree
posted on 2024-11-26 10:59:13 | under | source
小清新题。
一棵子树对外界的影响只关注其黑、白权值之和。考虑 \(u\) 子树,令 \(u\) 为黑色,那么黑点权值确定,不难发现白点权值应当尽量小,因为本题只需满足点权非负即可,所以白点权值较大的方案一定可以通过将权值移到 \(u\) 父亲的方式转化为权值和较小的方案。
那么进行树形 dp,目标是 \(u\) 子树黑点权值和为 \(X_u\) 且白点权值尽量小,\(u\) 权值随意所以令其它黑点权值和 \(\le X_u\) 即可。所以有状态 \(f_{u,i}\) 表示 \(u\) 子树黑点权值为 \(i\) 时白点权值和最小是多少。
考虑转移,记 \(g\) 为 \(f_u\) 的滚动数组,新增 \(v\) 子树那么分类讨论 \(v\) 的颜色(是否和 \(u\) 一样即可):
- 均为黑色:\(f_{u,i+X_v}\gets g_i+f_{v,X_v}\)。
- 为白色:\(f_{u,f_{v,X_v}}\gets g_i+X_v\)。
读者可以结合贪心结论和 dp 转移来加深理解,其实本质是一样的:为了使第二种转移中尽量不越界,所以肯定要白点权值尽量小。
最后判断 \(f_{1,X_1}\) 是否有值,复杂度 \(O(nV)\)。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define MIN(a, b) a = min(a, b)
const int N = 1e3 + 5, M = 5e3 + 5, inf = 1e7;
int n, pa, a[N], f[N][M], g[M];
vector<int> to[N];
inline void dfs(int u){
for(int i = 0; i <= a[u]; ++i) f[u][i] = 0;
for(auto v : to[u]){
dfs(v);
for(int i = 0; i <= a[u]; ++i) g[i] = f[u][i], f[u][i] = inf;
for(int i = 0; i <= a[u]; ++i){
if(i + a[v] <= a[u]) MIN(f[u][i + a[v]], g[i] + f[v][a[v]]);
if(i + f[v][a[v]] <= a[u]) MIN(f[u][i + f[v][a[v]]], g[i] + a[v]);
}
}
}
signed main(){
cin >> n;
for(int i = 2; i <= n; ++i) scanf("%lld", &pa), to[pa].push_back(i);
for(int i = 1; i <= n; ++i) scanf("%lld", &a[i]);
dfs(1);
if(f[1][a[1]] < inf) puts("POSSIBLE");
else puts("IMPOSSIBLE");
return 0;
}

浙公网安备 33010602011771号