kZjPBD.jpg

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

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







柿子划一划
就成了 sigma ( w i  +  mid  )
wi 就是每条边操作的费用 然后再加上 二分的值
 

消圈定理:残量网络里如果存在负费用圈,那么当前流不是最小费用流。因为通过增加残量网络负权边的流量,减少正权边的流量,一定能得到另一个更优的可行流。

 
其实就是找负环
!!注意如果原图的流量为0的话,就不能建立减少流量的变了 qwq




 
 1 //sol1
 2 #include<cstdio>
 3 inline int read(){
 4     int x=0,f=1;char ch=getchar();
 5     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 6     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
 7     return x*f;
 8 }
 9 const int N=1e5+5;
10 struct edge{int v,w,next;}e[N];int tot,head[N];
11 int n,m,S,q[N],cnt[N];
12 bool vis[N];
13 double dis[N];
14 inline void add(int x,int y,int z){
15     e[++tot].v=y;e[tot].w=z;e[tot].next=head[x];head[x]=tot;
16 }
17 inline bool spfa(double plusx){
18     for(int i=1;i<=n;i++) vis[i]=0,cnt[i]=0,dis[i]=1e9;
19     unsigned short h=0,t=1;q[t]=S;dis[S]=0;cnt[S]=1;
20     while(h!=t){
21         int x=q[++h];vis[x]=0;
22         for(int i=head[x];i;i=e[i].next){
23             if(cnt[e[i].v]>n) return 1;
24             double length=(double)e[i].w+plusx;
25             if(dis[e[i].v]>dis[x]+length){
26                 dis[e[i].v]=dis[x]+length;
27                 if(!vis[e[i].v]){
28                     vis[e[i].v]=1;
29                     cnt[e[i].v]++;
30                     q[++t]=e[i].v;
31                 }
32             }
33         }
34     }
35     return 0;
36 } 
37 int main(){
38     double l=0,r=0,mid,ans;
39     n=read()+2;m=read();S=n-1;
40     for(int i=1,a,b,c,d,u,v;i<=m;i++){
41         u=read();v=read();a=read();b=read();c=read();d=read();
42         add(u,v,b+d);
43         if(c) add(v,u,a-d);
44         if(a-d<0) r+=(double)(d-a);
45     }
46     while(r-l>=1e-3){
47         mid=(l+r)/2.00;
48         if(spfa(mid)) ans=mid,l=mid;
49         else r=mid;
50     }
51     printf("%.2lf",ans);
52     return 0;
53 }

 

 
 
 
 
 
 
 
 
 
 
posted @ 2019-06-21 15:18  Through_The_Night  阅读(164)  评论(0编辑  收藏  举报