zoukankan      html  css  js  c++  java
  • IndiaHacks 2016

    这题思路很简单,二分m,求最大流是否大于等于x。

    但是比赛过程中大部分的代码都被hack了。。。

    精度问题,和流量可能超int

    关于精度问题,这题真是提醒的到位,如果是先用二分将精度控制在10^-8左右,最后乘一个10^4,精度只能在10-4,而二分控制精度在10^-11很容易死循环(因为double 保存15-16位有效数字,结果可能为10^6级,精确到10-11,double做不到)

    所以这题二分可以不写成while(d-b>eps),而直接规定二分的次数,设置成100次,基本可以保证14-15位有效数字都正确了,这时再乘10^4还是能够达到题目中要求的10^-6的精度。

    还有一种处理精度的方法:

    直接定义上下界就为输出的最后结果,在判断的过程中除以x,最后输出也能满足要求。

    第一种精度处理方式:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <vector>
    #include <math.h>
    #include <iostream>
    using namespace std;
    #define eps 1e-11
    #define N 55
    #define M 500500
    #define INF 0x3fffff
    
    
    
    struct node1
    {
        long long to,w,next;
    }edge[M];
    
    long long sn,sm,sx;
    long long pre[10*N];
    long long g[N][N];
    long long gap[10*N],lv[10*N];
    long long k,c,m;
    long long cnt;
    long long n,nn;
    long long s,t;
    long long ans;
    long long sum;
    
    
    void add_edge(long long u,long long v,long long w)
    {
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].next=pre[u];
        pre[u]=cnt++;
    }
    
    long long gdfs(long long k,long long w)
    {
        if(k==t) return w;
        long long f=0;
        long long mi=nn-1;
        for(long long p=pre[k];p!=-1;p=edge[p].next)
        {
            long long v=edge[p].to,tw=edge[p].w;
            if(tw!=0)
            {
                if(lv[k]==lv[v]+1)
                {
                    long long tmp=gdfs(v,min(tw,w-f));
                    f+=tmp;
                    edge[p].w-=tmp;
                    edge[p^1].w+=tmp;
                    if(f==w||lv[s]==nn) break;
                }
                if(lv[v]<mi) mi=lv[v];
            }
        }
        if(f==0)
        {
            gap[lv[k]]--;
            if( gap[ lv[k] ]==0 )
            {
                lv[s]=nn;
            }
            lv[k]=mi+1;
            gap[lv[k]]++;
        }
        return f;
    }
    
    long long sap()
    {
        memset(lv,0,sizeof(lv));
        memset(gap,0,sizeof(gap));
        gap[0]=nn;
        while(lv[s]<nn)
        {
            sum+=gdfs(s,INF);
        }
        return sum;
    }
    
    long long a[505],b[505],kk[505];
    
    long long check(double mid)
    {
        sum=0;
        //mid/=sx;
        memset(pre,-1,sizeof(pre));
        cnt=0;
        
        for(long long i=0;i<sm;i++)
        {
            add_edge(a[i],b[i],(long long)(kk[i]/mid+eps));
            add_edge(b[i],a[i],0);
        }
        if(sap()>=sx)
        {
            return 1;
        }
        else return 0;
    }
    
    
    
    int main()
    {
        cin>>sn>>sm>>sx;
        for(long long i=0;i<sm;i++)
        {
            cin>>a[i]>>b[i]>>kk[i];
        }
        
        s=1;
        t=sn;
        nn=t+1;
        
        //这个精度问题还是很坑。。。
        double b=0,d=10000000.0;
        //好坑的东西! 我就操!
        int time=160;
        while(time--)//这里精度太小,竟然会死循环。。。
        {
            double mid=(b+d)/2;
            if( check(mid)==1 )
            {
                b = mid;
            }
            else
            {
                d = mid;
            }
        }
        printf("%.10lf",b*sx);
        return 0;
    }

    第二种精度处理方式:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <vector>
    #include <math.h>
    #include <iostream>
    using namespace std;
    #define eps 1e-11
    #define N 55
    #define M 500500
    #define INF 0x3fffff
    
    
    
    struct node1
    {
        long long to,w,next;
    }edge[M];
    
    long long sn,sm,sx;
    long long pre[10*N];
    long long g[N][N];
    long long gap[10*N],lv[10*N];
    long long k,c,m;
    long long cnt;
    long long n,nn;
    long long s,t;
    long long ans;
    long long sum;
    
    
    void add_edge(long long u,long long v,long long w)
    {
        edge[cnt].to=v;
        edge[cnt].w=w;
        edge[cnt].next=pre[u];
        pre[u]=cnt++;
    }
    
    long long gdfs(long long k,long long w)
    {
        if(k==t) return w;
        long long f=0;
        long long mi=nn-1;
        for(long long p=pre[k];p!=-1;p=edge[p].next)
        {
            long long v=edge[p].to,tw=edge[p].w;
            if(tw!=0)
            {
                if(lv[k]==lv[v]+1)
                {
                    long long tmp=gdfs(v,min(tw,w-f));
                    f+=tmp;
                    edge[p].w-=tmp;
                    edge[p^1].w+=tmp;
                    if(f==w||lv[s]==nn) break;
                }
                if(lv[v]<mi) mi=lv[v];
            }
        }
        if(f==0)
        {
            gap[lv[k]]--;
            if( gap[ lv[k] ]==0 )
            {
                lv[s]=nn;
            }
            lv[k]=mi+1;
            gap[lv[k]]++;
        }
        return f;
    }
    
    long long sap()
    {
        memset(lv,0,sizeof(lv));
        memset(gap,0,sizeof(gap));
        gap[0]=nn;
        while(lv[s]<nn)
        {
            sum+=gdfs(s,INF);
        }
        return sum;
    }
    
    long long a[505],b[505],kk[505];
    
    long long check(long double mid)
    {
        sum=0;
        mid/=sx;
        memset(pre,-1,sizeof(pre));
        cnt=0;
        
        for(long long i=0;i<sm;i++)
        {
            add_edge(a[i],b[i],(long long)(kk[i]/mid+eps));
            add_edge(b[i],a[i],0);
        }
        if(sap()>=sx)
        {
            return 1;
        }
        else return 0;
    }
    
    
    
    int main()
    {
        cin>>sn>>sm>>sx;
        for(long long i=0;i<sm;i++)
        {
            cin>>a[i]>>b[i]>>kk[i];
        }
        
        s=1;
        t=sn;
        nn=t+1;
        
        //这个精度问题还是很坑。。。
        long double b=0,d=1000000000.0;
        //好坑的东西! 我就操!
        while(d-b > 1e-13)//这里精度太小,竟然会死循环。。。
        {
            long double mid=(b+d)/2;
            if( check(mid)==1 )
            {
                b = mid;
            }
            else
            {
                d = mid;
            }
        }
        printf("%.20Lf",b);
        return 0;
    }
  • 相关阅读:
    JS面试题(一)
    cookie、locakstorage、sessionstorage的区别
    BOM操作
    DOM表单(复选框)
    DOM表格操作
    Javascript的组成——EMACScript、DOM、BOM
    scrollto 到指定位置
    编写一个javscript函数 fn,该函数有一个参数 n(数字类型),其返回值是一个数组,该数组内是 n 个随机且不重复的整数,且整数取值范围是 [2, 32]。
    使用bluebird解决promise兼容性问题
    Mac 更改/usr/bin 目录权限失败
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/5297542.html
Copyright © 2011-2022 走看看