IndiaHacks 2016 - Online Edition (CF) . D

这题思路很简单,二分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;
}
时间: 2024-10-12 18:50:48

IndiaHacks 2016 - Online Edition (CF) . D的相关文章

IndiaHacks 2016 - Online Edition (Div. 1 + Div. 2) 二分答案 + 网络流

这道题的意思是给你一个有向图, 每条边上有一个最大载重量, 现在有x头牛要从顶点1走向顶点n, 每头牛要载的重量都是一样的, 问你最多能载多少的重量? 可以二分答案, 算出每头牛的载重, 然后修改边权, 跑一次最大流即可判断当前答案是否正确, 二分答案即可, 注意由于原始边权/每头牛的载重量可能会很大, 因此我们在修改边权时应该注意这一点,将边权的最大值控制在1000000之内, 防止溢出, 代码如下: #include <bits/stdc++.h> using namespace std;

CodeForces 653 A. Bear and Three Balls——(IndiaHacks 2016 - Online Edition (Div. 1 + Div. 2))

传送门 A. Bear and Three Balls time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Limak is a little polar bear. He has n balls, the i-th ball has size ti. Limak wants to give one ball to each of

如何部署Windows Server 2016 中的Storage Spaces Direct超聚合解决方案

客户环境: Component   Detail Platform Dell  PowerEdge R730xd (2U, 16 x 3.5" and 2 x 2.5" rear drives) CPU 2 x 338-BJCZ  Intel Xeon CPU E5-2620 v4 @2.10GHz Memory 8 x  16 GB RDIMM, 2400MT/s, Dual rank, x8 Data Width OS  drive 200GB  SSD NDC Intel  X5

配置 Windows Server 2016 Storage Replica

存储副本 (Storage Replica) 是一种 Windows Server 技术,它允许针对灾难恢复在服务器或群集之间进行卷的同步复制. 它还允许你使用异步复制来创建跨越两个站点的故障转移群集,同时保持所有节点同步. 存储副本支持同步和异步复制: 同步复制映射低延迟网络站点中的数据和在崩溃时保持一致的卷,以确保在故障发生过程中文件系统级别的数据损失为零. 异步复制通过较高延迟网络链接映射都市范围外的站点之间的数据,但不保证在出现故障时两个站点具有完全相同的数据副本. 同步复制 同步复制可

Windows Server 2016 Volume Activation Tips

This is Scott McArthur, a Supportability Program Manager for Windows and Surface. With the launch of Windows Server 2016 I wanted to share some information on volume activation: Updating your existing KMS hosts to support Windows Server 2016 Setting

[转帖]Windows Server 2016各种版本介绍

Windows Server 2016各种版本介绍 http://www.5sharing.com/js/zx/872.html windows server的版本 时间:2018-10-06 10:21来源:原创 作者:5分享 点击: 550 次 Windows Server 2016 Essentials edition Windows Server 2016 Essentials版是专为小型企业而设计的.它对应于Windows Server的早期版本中的Windows Small Busi

Building Maintainable Software-java篇之Keep Architecture Components Balanced

Building encapsulation boundaries is a crucial skill in software architecture. -George H. Fairbanks in Just Enough Architecture Guideline: ? Balance the number and relative size of top-level components in your code. ? Do this by organizing source cod

SQL Server 诊断查询-(1)

SQL and OS Version information for current instance SELECT @@SERVERNAME AS [Server Name], @@VERSIONAS [SQL Server and OS Version Info]; Query #2 is Core Counts. Get socket, physical core and logical core count from the SQL Server Error log. EXEC sys.

Office CVE-2017-8570远程代码执行漏洞复现

实验环境 操作机:Kali Linux IP:172.16.11.2 目标机:windows7 x64 IP:172.16.12.2 实验目的 掌握漏洞的利用方法 实验工具 Metaspliot:它是一款开源的安全漏洞检测工具,可以帮助安全和IT专业人士识别安全性问题,验证漏洞的缓解措施,并管理专家驱动的安全性进行评估,提供真正的安全风险情报.这些功能包括智能开发,代码审计,Web应用程序扫描,社会工程,团队合作. 实验内容 Office CVE-2017-8570 CVE-2017-8570漏