loj2071 「JSOI2016」最佳团体

分数规划+树形依赖背包orz

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
int n, k, s[2505], p[2505], uu, dfn[2505], idx, fff[2505], fan[2505], hea[2505];
int cnt;
double dp[2505][2505];
struct Edge{
    int too, nxt;
}edge[5005];
void add_edge(int fro, int too){
    edge[++cnt].nxt = hea[fro];
    edge[cnt].too = too;
    hea[fro] = cnt;
}
void dfs(int x, int f){
    dfn[x] = ++idx;
    fan[idx] = x;
    for(int i=hea[x]; i; i=edge[i].nxt){
        int t=edge[i].too;
        if(t!=f)    dfs(t, x);
    }
    fff[dfn[x]] = idx + 1;
}
bool chk(double mid){
    memset(dp, 0xcf, sizeof(dp));
    dp[1][0] = 0;
    for(int i=1; i<=n+1; i++)
        for(int j=0; j<=k; j++){
            dp[i+1][j+1] = max(dp[i+1][j+1], dp[i][j]+p[fan[i]]-mid*s[fan[i]]);
            dp[fff[i]][j] = max(dp[i][j], dp[fff[i]][j]);
        }
    return dp[n+2][k]>=0;
}
int main(){
    cin>>k>>n;
    k++;
    for(int i=1; i<=n; i++){
        scanf("%d %d %d", &s[i], &p[i], &uu);
        add_edge(i, uu);
        add_edge(uu, i);
    }
    dfs(0, 0);
    double l=0.0, r=1e4, mid, re;
    while(fabs(r-l)>=1e-6){
        mid = (l + r) / 2.0;
        if(chk(mid))    re = mid, l = mid;
        else    r = mid;
    }
    printf("%.3f\n", re);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/poorpool/p/9046472.html