zoukankan      html  css  js  c++  java
  • 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
    ",l*p);
    }
    

      

  • 相关阅读:
    Vue 冷知识(一)
    Google Chrome 谷歌浏览器 调试被坑之路
    全选、全不选、反选
    赋值运算符
    JS 数组的常用方法归纳之不改变原数组和其他
    CSS控制文字,超出部分显示省略号
    火狐浏览器解决跨域问题
    JS 数组的常用方法详解归纳之改变原数组方法
    vue项目 多文件上传并显示在页面上
    二叉搜索树操作
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6271187.html
Copyright © 2011-2022 走看看