题解:AT_arc096_d [ARC096F] Sweet Alchemy
huhaoming2011 · · 题解
背包妙妙题。
首先,转换一下题意,因为原来具有依赖性,不太好处理(
还是不好做,为什么呢?因为除了
有什么用呢?很大用处!根据刚刚的贪心,可以得到,最优的答案当中,对于
但是直接这样搞肯定不方便,反正
价值比较小,大概是
代码如下
#include<bits/stdc++.h>
#define int long long
#define pii pair<int,int>
using namespace std;
const int inf = 1e16 + 7;
const int N = 50 + 7;
const int M = 1e6 + 7;
int n, m, d, fa[N], w[N], v[N], id[N], c[N], ans, lim, f[N * N * N];
vector<int> G[N];
vector<pii> b;
void dfs(int x)
{
v[x] = 1;
for(int to : G[x])
{
dfs(to);
w[x] += w[to];
v[x] += v[to];
}
}
signed main()
{
cin.tie(0)->sync_with_stdio(0);
cin >> n >> m >> d;
cin >> w[1]; id[1] = 1;
for(int i = 2; i <= n; i++)
{
cin >> w[i] >> fa[i];
G[fa[i]].push_back(i);
id[i] = i, c[i] = d;
}
dfs(1), c[1] = m / w[1];
sort(id + 1, id + n + 1, [&](int x, int y){return v[x] * w[y] > v[y] * w[x];});
for(int i = 1; i <= n; i++)
{
int mn = min(n, c[i]);
lim += mn * v[i];
for(int j = 1; j <= mn; j <<= 1)
{
b.push_back({j * v[i], j * w[i]});
mn -= j;
}
if(mn) b.push_back({mn * v[i], mn * w[i]});
}
for(int i = 1; i <= lim; i++)
f[i] = inf;
for(auto[V, W] : b)
for(int i = lim; i >= V; i--)
f[i] = min(f[i], f[i - V] + W);
for(int i = 0; i <= lim; i++)
{
if(f[i] > m) continue ;
int cur = i, re = m - f[i];
for(int j = 1; j <= n; j++)
{
int tot = min(c[id[j]] - min(n, c[id[j]]), re / w[id[j]]);
re -= tot * w[id[j]], cur += tot * v[id[j]];
}
ans = max(ans, cur);
}
cout << ans;
return 0;
}