Description
Input
Output
Sample Input
1 2
1000 1 0
1 1000 1
Sample Output
0.001
Data Constraint
思路
看到这种最值问题,肯定要二分啦!
二分一个mid,满足sigma(pi)/sigma(si)>=mid
发现不好处理,所以乱搞一下
移项!!
sigma(pi)>=midsigma(si)
sigma(pi)-midsigma(si)>=0
发现每个点可以单独考虑,权值为pi-si*mid
问题就变成了经典的树上背包问题
这题n3logn可以过
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#define db double
using namespace std;
const db E=1e-5;
const int maxn=3577;
int list[maxn],k,n,si[maxn],cnt;
db s[maxn],p[maxn],f[maxn][maxn],mid;
struct edge
{
int to,next;
}e[maxn];
void add(int u,int v)
{
e[++cnt].to=v; e[cnt].next=list[u]; list[u]=cnt;
}
void dfs(int u,int mx)
{
si[u]=1;
if(mx==0) return;
for(int i=list[u]; i; i=e[i].next)
{
int v=e[i].to;
dfs(v,mx-1);
si[u]+=si[v];
for(int j=min(mx-1,si[u]); j; j--)
for(int k=min(j,si[v]); k; k--)
{
f[u][j]=max(f[v][k]+f[u][j-k],f[u][j]);
}
}
for(int i=min(mx,si[u]); i; i--)
f[u][i]=f[u][i-1]+p[u]-s[u]*mid;
}
int main()
{
scanf("%d%d",&k,&n);
for(int i=1; i<=n; i++)
{
int x;
scanf("%lf%lf%d",&s[i],&p[i],&x);
add(x,i);
}
db l=0,r=3;
while(l+E<r)
{
mid=(l+r)/2;
memset(f,0xf7,sizeof(f));
for(int i=0; i<=n; i++) f[i][0]=0;
dfs(0,k+1);
if(f[0][k+1]>=0) l=mid+E;else r=mid-E;
}
printf("%.3lf",(l+r)/2);
}