Codeforces 815C Karen and Supermarket 树形dp

时间:2021-09-17 03:22:37

Karen and Supermarket

感觉就是很普通的树形dp。

dp[ i ][ 0 ][ u ]表示在 i 这棵子树中选择 u 个且 i 不用优惠券的最小花费。

dp[ i ][ 1 ][ u ]表示在 i 这棵子树中选择 u 个且 i 用优惠券的最小花费。

注意这个转移总的合起来是O(n ^ 2)的。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long
using namespace std; const int N = + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + ;
const double eps = 1e-; int n, b, d[N], c[N], fa[N];
vector<int> G[N]; int dp[N][][N];
int tmp[N][][N];
int sum[N]; void dfs(int u) {
sum[u] = ;
memset(dp[u], inf, sizeof(dp[u]));
dp[u][][] = ;
dp[u][][] = c[u];
dp[u][][] = c[u] - d[u];
for(auto& v : G[u]) {
dfs(v);
memset(tmp[u], INF, sizeof(tmp[u]));
for(int i = ; i <= sum[u]; i++) {
for(int j = ; j <= sum[v]; j++) {
tmp[u][][i + j] = min(tmp[u][][i + j], dp[u][][i] + dp[v][][j]);
tmp[u][][i + j] = min(tmp[u][][i + j], dp[u][][i] + dp[v][][j]);
tmp[u][][i + j] = min(tmp[u][][i + j], dp[u][][i] + dp[v][][j]);
}
}
sum[u] += sum[v];
memcpy(dp[u], tmp[u], sizeof(dp[u]));
}
} int main() {
scanf("%d%d", &n, &b);
for(int i = ; i <= n; i++) {
scanf("%d%d", &c[i], &d[i]);
if(i > ) {
scanf("%d", &fa[i]);
G[fa[i]].push_back(i);
}
}
dfs();
for(int i = n; i >= ; i--) {
if(dp[][][i] <= b || dp[][][i] <= b) {
printf("%d\n", i);
return ;
}
}
return ;
} /*
*/