【BZOJ3597】【SCOI2014】—方伯伯运椰子(分数规划)
显然流量不变的时候是最优的
考虑如果把一条边流量减一
花费是
扩大一次花费是
想象一下,实际上最优操作就是对于2条起点终点相同的有向路径
压缩一条,扩大一条
把扩大看成正向,压缩看成反向的
实际上就变成了一个环
实际上我们现在就是要让一个环上的最小
因为有边的数量
考虑分数规划
则
即
二分
每条边加上,看有没有负环,有则,否则
#include<bits/stdc++.h>
using namespace std;
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
return res;
}
const int N=3005,M=5005;
const int inf=1e9;
const double eps=1e-6;
int str,des,adj[N],nxt[M<<1],to[M<<1],val[M<<1],vis[N],in[N],cnt,n,m;
double tp[M<<1],dis[M<<1];
inline void addedge(int u,int v,int w){
nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,val[cnt]=w;
}
inline bool spfa(){
for(int i=1;i<=n+2;i++)dis[i]=inf;
memset(vis,0,sizeof(vis));queue<int> q;
dis[str]=0;in[str]=1;
q.push(str);memset(in,0,sizeof(in));
while(!q.empty()){
int u=q.front();vis[u]=0,q.pop();
for(int e=adj[u];e;e=nxt[e]){
int v=to[e];
if(dis[v]>dis[u]+tp[e]){
dis[v]=dis[u]+tp[e],in[v]=in[u]+1;
if(in[v]>n+2)return 1;
if(!vis[v]){
vis[v]=1,q.push(v);
}
}
}
}
return 0;
}
inline bool check(double k){
for(int i=1;i<=cnt;i++)tp[i]=1.0*val[i]+k;
return spfa();
}
int main(){
n=read(),m=read();
str=n+1,des=n+2;
for(int i=1;i<=m;i++){
int u=read(),v=read(),a=read(),b=read(),c=read(),d=read();
if(c!=0)addedge(v,u,a-d);
addedge(u,v,b+d);
}
double l=-1e6,r=1e6;
while(l+eps<r){
double mid=(l+r)/2;
if(check(mid))l=mid;
else r=mid;
}
printf("%.2lf",l);
}