首页 > 代码库 > BZOJ 3130 [Sdoi2013]费用流 ——网络流

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);
}

  

BZOJ 3130 [Sdoi2013]费用流 ——网络流