[JSOI2016]最佳团体
链接:https://www.luogu.com.cn/problem/P4322
题目描述:给定一棵树,每个节点有两个权值,每个节点要选了它的父亲节点才能选,求选个人后的和除以的和的最小值。
题解:话说这道题我只会,尽管复杂度不对但还是水过了洛谷的数据。
的和除以的和的最小值让我们很容易想到分数规划,然后这道题就变成了一道树型。
我们可以令表示在的子树中选个节点的最小代价。
则,这样是的。
然后我们时将每一个点将的上界设为,转移时的下界设为,据说这样就是的了。
#include<iostream>
#include<cstdio>
using namespace std;
struct node
{
int v,nxt;
};
node edge[2501];
int len,head[2501],fa[2501],sz[2501],k,n,R[2501],S[2501],P[2501];
double delta[2501],dp[2501][2502];
bool used[2501];
inline void add(register int x,register int y)
{
edge[++len].v=y;
edge[len].nxt=head[x];
head[x]=len;
return;
}
inline void dfs(register int x)
{
dp[x][1]=delta[x];
sz[x]=used[x]=1;
for (register int i=head[x];i>0;i=edge[i].nxt)
if (!used[edge[i].v])
{
dfs(edge[i].v);
fa[edge[i].v]=x;
sz[x]+=sz[edge[i].v];
}
for (register int i=head[x];i>0;i=edge[i].nxt)
if (fa[edge[i].v]==x)
for (int j=sz[x];j>=2;--j)
for (int k=max(1,j-sz[x]+sz[edge[i].v]);k<=min(sz[edge[i].v],j);++k)
dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[edge[i].v][k]);
return;
}
inline bool check(register double L)
{
for (register int i=1;i<=n;++i)
delta[i]=P[i]-L*S[i];
for (register int i=0;i<=n;++i)
{
used[i]=0;
for (int j=0;j<=n+1;++j)
dp[i][j]=-1e9;
}
dfs(0);
return dp[0][k]>=0;
}
inline int read()
{
register char c=0;
register int sum=0;
while (c<'0'||c>'9')
c=getchar();
while (c>='0'&&c<='9')
{
sum=sum*10+c-'0';
c=getchar();
}
return sum;
}
int main()
{
k=read();
n=read();
k++;
for (int i=1;i<=n;++i)
{
S[i]=read();
P[i]=read();
R[i]=read();
add(R[i],i);
}
double first=0,last=1e9,mid;
while (first+1e-5<=last)
{
mid=(first+last)/2;
if (check(mid))
first=mid;
else
last=mid;
}
printf("%0.3lf\n",first);
return 0;
}
作者:zhouhuanyi
出处:https://www.cnblogs.com/zhouhuanyi/p/16983673.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具