题目链接:https://www.luogu.com.cn/problem/P4322
解题思路:
01分数规划 + 树上背包。
下面的代码是 \(O(n^3)\) 的解法(不开O2会TLE一组数组):
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2505;
int K, n, a[maxn], b[maxn], p[maxn], sz[maxn];
double f[maxn][maxn], v[maxn];
vector<int> g[maxn];
void dfs(int u) {
sz[u] = 1;
f[u][0] = 0;
f[u][1] = v[u];
for (int i = 2; i <= K+1; i ++) f[u][i] = -1e9;
for (auto v: g[u]) {
dfs(v);
sz[u] += sz[v];
for (int j = min(K+1, sz[u]); j >= 1; j --)
for (int k = 1; k <= min(sz[v], j-1); k ++)
f[u][j] = max(f[u][j], f[u][j-k] + f[v][k]);
}
}
bool check(double mid) {
for (int i = 1; i <= n; i ++) v[i] = a[i] - mid * b[i];
dfs(0);
return f[0][K+1] >= 0;
}
int main() {
cin >> K >> n;
for (int i = 1; i <= n; i ++) {
cin >> b[i] >> a[i] >> p[i];
g[ p[i] ].push_back(i);
}
double L = 0, R = 10000.0;
while (R - L > 1e-4) {
double mid = (L + R) / 2;
if (check(mid)) L = mid;
else R = mid;
}
printf("%.3lf\n", L);
return 0;
}
树上背包有 \(O(n^2)\) 的解法,抽时间学会了补上。