传送门
题意:N个牧场,可供修建的道路有M条.奶牛负责修建道路,将所有牧场连通,获得报酬F.每条道路都有自己的施工时间ti和建造成本ci.连接两个相同的牧场的道路可能有多条.保证所有的牧场必定是可连通的,不过也有可能一些道路的建造成本之和会超过F.求选择修建哪些道路,使单位时间的利润(即总利润和总施工时间的比值)的最大.
分析:理解清楚题意,可以得出我们要求的实际上就是\((F-\sum{c_i})/\sum{t_i}\)
令\(x=(F-\sum{c_i})/\sum{t_i}\)
整理一下得,\(F-(\sum{c_i}+\sum{t_i}*x)=0\)
令\(f(x)=F-(\sum{c_i}+\sum{t_i}*x)\)
f(x)随x增大而减小,即f(x)是一个递减函数,既然具有单调性,就要想到二分答案.
我们直接二分要求的答案x,每一次check时把每条边的边权wi更新为\(ci+ti*x\),然后跑一遍最小生成树,最后判断权值总和与F的大小关系.
注意本题是实数域上的二分答案
const double eps=1e-6;
int n,m,f,fa[405];
struct edge{
int x,y,c,t;
double w;
}e[10005];
bool cmp(edge x,edge y){return x.w<y.w;}
int find(int x){
if(fa[x]==x)return x;
return fa[x]=find(fa[x]);
}
bool check(double mid){
for(int i=1;i<=m;i++)
e[i].w=e[i].c*1.0+e[i].t*mid;
sort(e+1,e+m+1,cmp);
for(int i=1;i<=n;i++)fa[i]=i;
int k=0;double now=0;
for(int i=1;i<=m;i++){
int x=find(e[i].x),y=find(e[i].y);
if(x!=y){
k++;
fa[y]=x;
now+=e[i].w;
if(now>f)return 0;
if(k==n-1)break;
}
}
return 1;
}
int main(){
n=read();m=read();f=read();
for(int i=1;i<=m;i++){
e[i].x=read();
e[i].y=read();
e[i].c=read();
e[i].t=read();
}
double l=-1e9,r=1e9,mid;
while(l+eps<r){
mid=(l+r)/2;
if(check(mid))l=mid;
else r=mid;
}
if(r<0)puts("0.0000");
else printf("%.4lf\n",r);
return 0;
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
· Linux系列:如何调试 malloc 的底层源码
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· 对象命名为何需要避免'-er'和'-or'后缀
· JDK 24 发布,新特性解读!
· .NET Core奇技淫巧之WinForm使用Python.NET并打包
· Java24你发任你发,我用Java8
· .NET 10 Preview 2 增强了 Blazor 和.NET MAUI