[JSOI2016]最佳團體【01分數規劃】【樹形揹包】

題目鏈接:https://www.luogu.org/problem/P4322

兩個板子合一塊

#include <bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define pb push_back
using namespace std;
const int N = 2600;
int n,m;
int siz[N],a[N],b[N];
double s[N],dp[N][N];
vector<int>nxt[N];
void dfs(int u) {        //時間複雜度O(N*M)
    siz[u] = 1;
    dp[u][0] = 0;
    dp[u][1] = s[u];
    for(auto v:nxt[u]) {
        dfs(v);
        per(i, min(siz[u],m), 1) {
            int P = min(siz[v],m-i);
            per(j, P, 0)
                dp[u][i+j] = max(dp[u][i+j],dp[u][i]+dp[v][j]);
        }
        siz[u] += siz[v];
    }
}
bool ok(double mid) {
    rep(i, 0, n)
        rep(j, 0, m)
            dp[i][j] = -1e9;
    rep(i, 1, n) s[i] = a[i]-mid*b[i];
    dfs(0);
    return dp[0][m]>=0;
}
int main() {
    //freopen("a.txt","r",stdin);
    scanf("%d%d",&m,&n);
    rep(i, 1, n) {
        int f;
        scanf("%d%d%d",&b[i],&a[i],&f);
        nxt[f].pb(i);
    }
    m++;
    dfs(0);
    double l = 0, r = 1e9;
    rep(i, 1, 50) {
        double mid = (l+r)/2;
        if(ok(mid)) l = mid;
        else r = mid;
    }
    printf("%.3f",l);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章