隐藏页面特效

3597: [Scoi2014]方伯伯运椰子[分数规划]

 

3597: [Scoi2014]方伯伯运椰子

Time Limit: 30 Sec  Memory Limit: 64 MB
Submit: 404  Solved: 249
[Submit][Status][Discuss]

Description

 

Input

 第一行包含二个整数N,M

接下来M行代表M条边,表示这个交通网络
每行六个整数,表示Ui,Vi,Ai,Bi,Ci,Di
接下来一行包含一条边,表示连接起点的边

Output

一个浮点数,保留二位小数。表示答案,数据保证答案大于0

Sample Input

5 10
1 5 13 13 0 412
2 5 30 18 396 148
1 5 33 31 0 39
4 5 22 4 0 786
4 5 13 32 0 561
4 5 3 48 0 460
2 5 32 47 604 258
5 7 44 37 75 164
5 7 34 50 925 441
6 2 26 38 1000 22
 

Sample Output

103.00

HINT

 

 1<=N<=5000


 
0<=M<=3000

 
1<=Ui,Vi<=N+2

 
0<=Ai,Bi<=500

 
0<=Ci<=10000

 
0<=Di<=1000

 

Source

 

 

很显然是分数规划,假设当前二分的答案为ans

那么X - Y >= k*ans 即 Y + k*ans <= X
首先,题目保证了ans > 0,那么不等式成立,当Y < X,也就是能构造出更优的解
然后这张图给人很明显的网络流即视感--尝试构图
一开始整张图是满流的,,我们能做的,是修改一些边的容量,但是又得保证最大流不变
假设扩充了一条边的容量,,那么相邻一定要有条边相应减少--这样找下去一定会出一个环
对于原图的每条边(x,y,a,b,c,d)
从x到y连一条权值为b + d的边,代表容量扩充的费用
从y到x连一条权值为a - d的边,代表容量缩小的费用,该边仅当c > 0时存在
假如图中存在一个负环,那么修改流量时沿着这个环绕一圈,答案一定更优
而且因为容量限制,这个环不能无限绕,,所以是合法的
那么二分答案,对应修改边权,最后用SPFA判断是否存在负环据说这个叫绕圈法??             ——转自 CRZbulabula

//================================================

//sol1 #include<cstdio> inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int N=1e5+5; struct edge{int v,w,next;}e[N];int tot,head[N]; int n,m,S,q[N],cnt[N]; bool vis[N]; double dis[N]; inline void add(int x,int y,int z){ e[++tot].v=y;e[tot].w=z;e[tot].next=head[x];head[x]=tot; } inline bool spfa(double plusx){ for(int i=1;i<=n;i++) vis[i]=0,cnt[i]=0,dis[i]=1e9; unsigned short h=0,t=1;q[t]=S;dis[S]=0;cnt[S]=1; while(h!=t){ int x=q[++h];vis[x]=0; for(int i=head[x];i;i=e[i].next){ if(cnt[e[i].v]>n) return 1; double length=(double)e[i].w+plusx; if(dis[e[i].v]>dis[x]+length){ dis[e[i].v]=dis[x]+length; if(!vis[e[i].v]){ vis[e[i].v]=1; cnt[e[i].v]++; q[++t]=e[i].v; } } } } return 0; } int main(){ double l=0,r=0,mid,ans; n=read()+2;m=read();S=n-1; for(int i=1,a,b,c,d,u,v;i<=m;i++){ u=read();v=read();a=read();b=read();c=read();d=read(); add(u,v,b+d); if(c) add(v,u,a-d); if(a-d<0) r+=(double)(d-a); } while(r-l>=1e-3){ mid=(l+r)/2.00; if(spfa(mid)) ans=mid,l=mid; else r=mid; } printf("%.2lf",ans); return 0; }

 


__EOF__

本文作者shenben
本文链接https://www.cnblogs.com/shenben/p/6379769.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   神犇(shenben)  阅读(546)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示