【LOJ】#2071. 「JSOI2016」最佳团体

题解

01分数规划,二分加树背包……

代码

#include <bits/stdc++.h>
#define enter putchar('
')
#define space putchar(' ')
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define MAXN 2505
#define mo 999999137
#define pb push_back
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        res = res * 10 + c - '0';
        c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) out(x / 10);
    putchar('0' + x % 10);
}

int K,N,siz[MAXN];
db S[MAXN],P[MAXN],val[MAXN],dp[MAXN][MAXN],tmp[MAXN];
struct node {
    int to,next;
}E[MAXN * 2];
int head[MAXN],sumE;
void add(int u,int v) {
    E[++sumE].to = v;
    E[sumE].next = head[u];
    head[u] = sumE;
}
void Init() {
    read(K);read(N);
    int u;
    for(int i = 2 ; i <= N + 1; ++i) {
        scanf("%lf%lf%d",&S[i],&P[i],&u);++u;
        add(u,i);add(i,u);
    }
    ++N;
}
void dfs(int u,int fa) {
    siz[u] = 0;
    dp[u][0] = 0.0;
    for(int i = head[u] ; i ; i = E[i].next) {
        int v = E[i].to;
        if(v != fa) {
            dfs(v,u);
            for(int i = 0 ; i <= siz[u] + siz[v] ; ++i) tmp[i] = -1e9;
            for(int i = 0 ; i <= siz[u] ; ++i) {
                for(int j = 0 ; j <= siz[v] ; ++j) {
                    tmp[i + j] = max(tmp[i + j],dp[u][i] + dp[v][j]);
                }
            }
            siz[u] += siz[v];
            for(int i = 0 ; i <= siz[u] ; ++i) dp[u][i] = tmp[i];
        }
    }
    ++siz[u];
    for(int i = siz[u] ; i >= 1 ; --i) {
        dp[u][i] = dp[u][i - 1] + val[u];
    }
}
bool check(db mid) {
    for(int i = 1 ; i <= N ; ++i) {
        val[i] = P[i] - S[i] * mid;
    }
    dfs(1,0);
    return dp[1][K + 1] >= 0.0;
}
void Solve() {
    db L = 0,R = 1000;
    int cnt = 50;
    while(cnt--) {
        db mid = (L + R) / 2.0;
        if(check(mid)) L = mid;
        else R = mid;
    }
    printf("%.3lf
",L);
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Init();
    Solve();
    return 0;
}
原文地址:https://www.cnblogs.com/ivorysi/p/9536589.html