版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
01分数规划+树上背包
#include<bits/stdc++.h>
using namespace std;
inline int read()
{
int data=0;int w=1; char ch=0;
ch=getchar();
while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
return data*w;
}
const double eps=1e-5;
const int inf=1e4+10;
const int N=3000;
int n,k;
vector<int>e[N];
int s[N],p[N],sz[N];
double w[N],dp[N][N];
inline int dfs(int x){
dp[x][1]=w[x];sz[x]=1;
for(int i=0;i<e[x].size();i++){
int v=e[x][i]; dfs(v);
for(int j=sz[x];j>=1;j--){
for(int k=0;k<=sz[v];k++){
dp[x][j+k]=max(dp[x][j+k],dp[x][j]+dp[v][k]);
}
}
sz[x]+=sz[v];
}
}
bool check(double x){
memset(dp,-10,sizeof(dp));
for(int i=0;i<=n;i++) dp[i][0]=0;
for(int i=1;i<=n;i++) w[i]=(double)p[i]-s[i]*x;
dfs(0);return dp[0][k]>=0;
}
int main(){
k=read();n=read();++k;
for(int i=1;i<=n;i++){
s[i]=read();p[i]=read();int r=read();
e[r].push_back(i);
}
double l=0,r=1e4,mid,ans=0;
while(r-l>=eps){
mid=(l+r)/2;
if(check(mid)) {
ans=mid,l=mid+eps;
}
else r=mid;
}
printf("%.3lf\n",ans);
return 0;
}