您的位置:首页 > Web前端 > JavaScript

[bzoj4753][Jsoi2016]最佳团体 树上背包+二分

2017-06-05 08:53 351 查看

4753: [Jsoi2016]最佳团体

Time Limit: 20 Sec  Memory Limit:
512 MB

[Submit][Status][Discuss]

Description

JSOI信息学代表队一共有N名候选人,这些候选人从1到N编号。方便起见,JYY的编号是0号。每个候选人都由一位
编号比他小的候选人Ri推荐。如果Ri=0则说明这个候选人是JYY自己看上的。为了保证团队的和谐,JYY需要保证,
如果招募了候选人i,那么候选人Ri"也一定需要在团队中。当然了,JYY自己总是在团队里的。每一个候选人都有
一个战斗值Pi",也有一个招募费用Si"。JYY希望招募K个候选人(JYY自己不算),组成一个性价比最高的团队。
也就是,这K个被JYY选择的候选人的总战斗值与总招募总费用的比值最大。

Input

输入一行包含两个正整数K和N。
接下来N行,其中第i行包含3个整数Si,Pi,Ri表示候选人i的招募费用,战斗值和推荐人编号。
对于100%的数据满足1≤K≤N≤2500,0<"Si,Pi"≤10^4,0≤Ri<i

Output

输出一行一个实数,表示最佳比值。答案保留三位小数。

Sample Input

1 2

1000 1 0

1 1000 1

Sample Output

0.001

HINT

Source

先跑一遍dfs序,f[i][j]表示前i个点,j个人

精度最重要

#include<iostream>
#include<cstdio>
using namespace std;
const int N = 2505;
double fabs( double x ){ return (x>0)?x:-x; }
int K,n;
double s
,p
,l,r,mid,f

,w
;
int last
,cnt,top
,size
;
struct Edge{ int to,next; }e[N*2];
void insert( int u, int v ){ e[++cnt].to = v; e[cnt].next = last[u]; last[u] = cnt; }
void dfs( int x ){
top[x] = ++top[0];
w[top[x]] = p[x] - mid * s[x];
for( int i = last[x]; i; i = e[i].next ) dfs(e[i].to);
size[top[x]] = top[0]-top[x]+1;
}
bool dp(){
top[0] = 0; dfs(n+1);
for( int i = 1; i <= n+2; i++ ) for( int j = 0; j <= K; j++ ) f[i][j] = -1000000000.0;
f[1][0] = 0;
for( int i = 1; i <= n+1; i++ )
for( int j = 0; j <= K; j++ ){
f[i+1][j+1] = max(f[i+1][j+1],f[i][j]+w[i]);
f[i+size[i]][j] = max(f[i][j],f[i+size[i]][j]);
}
return f[n+2][K] > -0.000000001;
}
int main(){
scanf("%d%d", &K, &n); K++;
for( int i = 1,rr; i <= n; i++ ){
scanf("%lf%lf%d", &s[i], &p[i], &rr);
insert( rr ? rr : n+1, i );
}
for( l = 1e-4, r = 1e4; fabs(r-l) > 1e-5; ){
mid = ( l + r )/ 2.0;
if(dp()) l = mid; else r = mid;
}
printf("%.3lf",l);
return 0;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: