可以看出是分数规划
然后我们可以看出其实只需要改变1的流量就可以了,因为每次改变要保证流量守恒,必须流成一个环,在正负性确定的情况下,变几次是无所谓的。
然后按照套路,设
[ ans=frac{X-Y}{k}\ anstimes k =X-Y\ anstimes k=-sum w_i\ sum ans-w_i=0 ]
从第二部到第三步是把X和Y中的共同边都减掉了
(w)是根据扩容或者缩容建的边权为(b+d,a-d)的边权集合
注意一点,缩小容量必须(c_i>0)
然后发现环的边数就是(k),减过去就可以二分ans了
Code:
#include <cstdio>
#include <cctype>
#include <cstring>
template <class T>
void read(T &x)
{x=0;char c=getchar();while(!isdigit(c)) c=getchar();while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
const int N=5010;
const int M=6010;
int n,m,u[N],v[N],a[N],b[N],c[N],d[N];
int head[N],to[M],Next[M],cnt;double edge[M];
void add(int u,int v,double w)
{to[++cnt]=v,edge[cnt]=w,Next[cnt]=head[u],head[u]=cnt;
}
int used[N],vis[N],q[N*N],l,r;double dis[N];
bool spfa()
{for(int i=1;i<=n+2;i++) dis[i]=1e12;memset(vis,0,sizeof vis);memset(used,0,sizeof used);dis[q[l=r=1]=n+1]=0;while(l<=r){int now=q[l++];used[now]=0;for(int v,i=head[now];i;i=Next[i])if(dis[v=to[i]]>dis[now]+edge[i]){dis[v]=dis[now]+edge[i];if((++vis[v])==n+2) return true;if(!used[v]) used[q[++r]=v]=1;}}return false;
}
bool check(double x)
{memset(head,0,sizeof head),cnt=0;for(int i=1;i<=m;i++){if(u[i]!=n+1){if(c[i]!=0) add(v[i],u[i],x+a[i]-d[i]);add(u[i],v[i],x+b[i]+d[i]);}elseadd(u[i],v[i],0);}return spfa();
}
int main()
{read(n),read(m);double l=0,r=0;for(int i=1;i<=m;i++){read(u[i]),read(v[i]),read(a[i]);read(b[i]),read(c[i]),read(d[i]);r+=1.0*c[i]*d[i];}while(l+1e-6<r){double mid=(l+r)/2;if(check(mid)) l=mid;else r=mid;}printf("%.2lfn",l);return 0;
}
2019.2.24
转载于:.html
本文发布于:2024-01-31 13:08:39,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170667772228754.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |