BZOJ 3130 [Sdoi2013]费用流 ——网络流
【题目分析】
很容易想到,可以把P放在流量最大的边上的时候最优。
所以二分网络流,判断什么时候可以达到最大流。
流量不一定是整数,所以需要实数二分,整数是会WA的。
【代码】
#include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> //#include <map> #include <set> #include <queue> #include <string> #include <iostream> #include <algorithm> using namespace std; #define maxn 1005 #define me 50005 #define inf 0x3f3f3f3f #define F(i,j,k) for (int i=j;i<=k;++i) #define D(i,j,k) for (int i=j;i>=k;--i) #define eps 1e-8 void Finout() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); #endif } int Getint() { 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; } int h[me],to[me<<1],ne[me<<1]; double fl[me<<1]; int en=0,S=0,T=me-1; int lim[me]; void add(int a,int b,double c) { // cout<<a<<" "<<b<<" "<<c<<endl; to[en]=b; ne[en]=h[a]; fl[en]=c; h[a]=en++; to[en]=a; ne[en]=h[b]; fl[en]=0; h[b]=en++; } int map[maxn],tag=0; bool tell() { queue <int> q; memset(map,-1,sizeof map); map[S]=0; q.push(S); while (!q.empty()) { int x=q.front(); q.pop(); for (int i=h[x];i>=0;i=ne[i]) { if (map[to[i]]==-1&&fl[i]>eps) { map[to[i]]=map[x]+1; q.push(to[i]); } } } if (map[T]!=-1) return true; return false; } double zeng(int k,double r) { if (k==T) return r; double ret=0; for (int i=h[k];i>=0&&ret<r;i=ne[i]) if (map[to[i]]==map[k]+1&&fl[i]>eps) { double tmp=zeng(to[i],min(fl[i],(double)r-ret)); ret+=tmp; fl[i]-=tmp; fl[i^1]+=tmp; } if (!ret) map[k]=-1; return ret; } int n,a[maxn],b[maxn],c[maxn],m,p; int main() { Finout(); memset(h,-1,sizeof h); n=Getint(); m=Getint(); p=Getint(); S=1;T=n; int maxx=0; F(i,1,m) { a[i]=Getint(); b[i]=Getint(); c[i]=Getint(); add(a[i],b[i],(double)c[i]); maxx=max(c[i],maxx); } double ans=0,tmp; while (tell()) while(tmp=zeng(S,(double)inf)) ans+=tmp; cout<<ans+eps<<endl; double l=0,r=(double)maxx; while (l+eps<r) { // cout<<l<<" "<<r<<endl; double mid=(l+r)/2; en=0;memset(h,-1,sizeof h); F(i,1,m) add(a[i],b[i],min(mid,(double)c[i])); double now=0,tmp; while (tell()) while (tmp=zeng(S,(double)inf)) now+=tmp; if (fabs(now-ans)<=eps) r=mid; else l=mid; } printf("%.5f\n",l*p); }