#include #include #include #include using namespace std; int n, k; int s[2501], p[2501], r[2501]; int treesize[2501]; vector child[2501]; double sum[2501][2502]; // trick: we use binary search to see if we can achieve a certain total profit // // if the guess is G, we want to know if there is some i1, i2, ..., ik such // that // // p(i1) + ... + p(ik) // ------------------- >= G // s(i1) + ... + s(ik) // // i.e. p(i1) + ... + p(ik) >= G * s(i1) + ... + G * s(ik) // i.e. p(i1) - G * s(i1) + ... + p(ik) - G * s(ik) >= 0 void compute(int node, double guess) { fill(sum[node], sum[node]+min(k, treesize[node])+1, -1e100); sum[node][0] = 0; sum[node][1] = (node ? p[node] - guess * s[node] : 0); int last = 1; for (auto c : child[node]) { compute(c, guess); for (int i = min(last,min(k, treesize[node])); i >= 1; i--) { for (int j = 0; j <= min(k, treesize[c]) && i+j <= min(k, treesize[node]); j++) { sum[node][i+j] = max(sum[node][i+j], sum[node][i] + sum[c][j]); last = max(last, i+j); } } } } bool possible(double guess) { compute(0, guess); return (sum[0][k] >= 0.0); } int main() { cin >> k >> n; k++; for (int i = 1; i <= n; i++) { cin >> s[i] >> p[i] >> r[i]; child[r[i]].push_back(i); } for (int i = n; i >= 0; i--) { treesize[i] = 1; for (auto c : child[i]) { treesize[i] += treesize[c]; } } double lo = 0; // lo possible, hi impossible double hi = 1.0; while (possible(hi)) { lo = hi; hi *= 2; } while (hi - lo > 1e-5) { double mid = (hi + lo) / 2.0; if (possible(mid)) { lo = mid; } else { hi = mid; } // cout << "lo = " << lo << ", hi = " << hi << endl; } cout << fixed << setprecision(3) << lo << endl; return 0; }