zoukankan      html  css  js  c++  java
  • BZOJ 3130: [Sdoi2013]费用流 网络流 二分 最大流

    https://www.lydsy.com/JudgeOnline/problem.php?id=3130

    本来找费用流的题,权当复习一下网络流好了。

    有点麻烦的是double,干脆判断大小或者二分增加下限都用eps=1e-8操作好了(毕竟只要求精确到4位)。

    我普通最大流都快忘了,板子写错了一次超时了。

    网络流板子的细节要记清楚:1.增广的时候访问完哪个点就把dep标记改为-1防止同一次增广再次访问。2.往下层传递的时候用val-cnt而不是val。3.cnt=val时及时返回。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<queue>
     7 using namespace std;
     8 const int maxn=1010;
     9 const double eps=1e-8;
    10 int n,m,p;double mx;
    11 struct nod{
    12     int y,rev,next;double v,v1;
    13 }e[maxn*2];
    14 int head[maxn]={},tot=0;double Ans=0;
    15 int num[maxn]={},vis[maxn*2]={};
    16 queue<int>q;
    17 void init(int x,int y,double v){
    18     e[++tot].y=y;e[tot].v=v;e[tot].rev=tot+1;e[tot].next=head[x];head[x]=tot;
    19     e[++tot].y=x;e[tot].v=0;e[tot].rev=tot-1;e[tot].next=head[y];head[y]=tot;
    20 }
    21 bool fir(){
    22     memset(num,-1,sizeof(num));
    23     q.push(1);num[1]=0;
    24     while(!q.empty()){
    25         int x=q.front();q.pop();
    26         for(int i=head[x];i;i=e[i].next){
    27             if(e[i].v1<eps)continue;
    28             if(num[e[i].y]==-1){
    29                 num[e[i].y]=num[x]+1;
    30                 q.push(e[i].y);
    31             }
    32         }
    33     }
    34     return num[n]!=-1;
    35 }
    36 double dfs(int x,double val){
    37     if(x==n)return val;
    38     double cnt=0,z;
    39     for(int i=head[x];i;i=e[i].next){
    40         if((e[i].v1<eps)||num[e[i].y]!=num[x]+1)continue;
    41         z=dfs(e[i].y,min(val-cnt,e[i].v1));
    42         cnt+=z; e[i].v1-=z; e[e[i].rev].v1+=z;
    43         if(val-cnt<eps)return cnt;
    44     }num[x]=-1;
    45     return cnt;
    46 }
    47 bool Check(double shu){
    48     mx=shu;double cnt=0;
    49     for(int i=1;i<tot;i+=2)e[i].v1=min(mx,e[i].v);
    50     for(int i=2;i<=tot;i+=2)e[i].v1=0;
    51     while(fir()){
    52         cnt+=dfs(1,50000000);
    53     }
    54     return Ans-cnt<eps;
    55 }
    56 double erfen(double mx){
    57     double l=0,r=mx;
    58     while(r-l>eps){
    59         double mid=(l+r)/2;
    60         if(Check(mid))r=mid;
    61         else l=mid+eps;
    62     }
    63     return l;
    64 }
    65 int main(){
    66     scanf("%d%d%d",&n,&m,&p);
    67     int x,y,z;
    68     for(int i=1;i<=m;i++){scanf("%d%d%d",&x,&y,&z);init(x,y,(double)z);mx=max(mx,(double)z);}
    69     for(int i=1;i<=tot;i++)e[i].v1=e[i].v;
    70     while(fir())Ans+=dfs(1,mx);
    71     if(Ans==0){
    72         printf("0
    0.0000
    ");
    73     }
    74     else{
    75         printf("%.0f
    ",Ans);
    76         printf("%.4lf
    ",erfen(mx)*(double)p);
    77     }
    78     return 0;
    79 }
    View Code

  • 相关阅读:
    ZJOI2006 物流运输
    codevs 1403 新三国争霸
    (一) MySQL学习笔记:MySQL安装图解
    多线程同步
    SendMessage和PostMessage区别
    VS2008 MFC 配置 Gdiplus
    IE7常用的几个快捷键 你常用的是哪个
    匆匆的六年 收获了什么
    python 代码题07 sorted函数
    python 代码题06 回数是指从左向右读和从右向左读都是一样的数,例如12321,909。请利用filter()筛选出回数
  • 原文地址:https://www.cnblogs.com/137shoebills/p/8876537.html
Copyright © 2011-2022 走看看