版权声明:因为我是蒟蒻,所以请大佬和神犇们不要转载(有坑)的文章,并指出问题,谢谢 https://blog.csdn.net/Deep_Kevin/article/details/83756897
正题
题目链接点这
如果我们给一条边加1的流量,那么费用是不是多了,给一条边减1的流量,那么费用多了。
这两个都是挺明显的吧。
考虑怎么保证流量平衡。
设原边为。
那么建两条边,,现在改一个环就可以使得流量平衡。
为什么?
假设这个环先走了一段一类边,再走了一段二类边,然后再走了一段一类边。。。。。。
那么在一类边的交点和二类边的交点的流量都是平衡的,二类边相当于反向边。画图看一下就明白了。
好,那么这个环的边权和就是。但是题目要我们求。
k为环的大小。
我们二分一个mid
然后令这个东西大于mid,看看发生什么。
因为Y-X是环的边权和,所以。
令新边权为,若能求出一个负环,那么说明答案比mid大,否则答案小于等于mid。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
int n,m;
struct new_edge{
int y,next;
double c;
}s[60010];
int first[5010],len=0;
double dis[5010];
bool tf[5010];
void ins(int x,int y,double c){
len++;
s[len]=(new_edge){y,first[x],c};first[x]=len;
}
bool dfs(int x,double temp){
tf[x]=true;
for(int i=first[x];i!=0;i=s[i].next){
int y=s[i].y;
if(dis[y]>dis[x]+s[i].c+temp){
if(tf[y]) return true;
dis[y]=dis[x]+s[i].c+temp;
if(dfs(y,temp)) return true;
}
}
return tf[x]=false;
}
int main(){
scanf("%d %d",&n,&m);
int x,y,a,b,c,d;
for(int i=1;i<=m;i++){
scanf("%d %d %d %d %d %d",&x,&y,&a,&b,&c,&d);
ins(x,y,b+d);
if(c) ins(y,x,a-d);
}
double l=0,r=1e7;
while(r-l>=1e-3){
for(int i=1;i<=n+2;i++) dis[i]=1e9,tf[i]=false;
dis[n+1]=0;
double mid=(l+r)/2;
if(dfs(n+1,mid)) l=mid;
else r=mid;
}
printf("%.2lf",l);
}