zoukankan      html  css  js  c++  java
  • bzoj 1221 软件开发 费用流

    应该比较好看出来是费用流,那么就考虑怎么构图

    首先我们把一天拆成两个点,XI,YI,分别代表这一天买了多少

    和洗多少,再加入源和汇S,T

    1.每一天我们可以买新的毛巾,所以连接一条从S到XI的边,流量为正无穷(因为可以买好多),费用为f

    2.然后我们对于买来的毛巾可以洗,每天都产生need[i]的毛巾可以洗,那么连一条从S到YI的边,

    流量为need[i],费用为0(因为只决定要洗,没有确定洗的方案,所以先不算费用)

    3.每一条要用a方法洗的毛巾,我们连一条从YI到X(I+a+1)的边,流量为正无穷(下文解释),费用为fa的

    4.每一条要用b方法洗的毛巾,我们连一条从YI到X(I+b+1)的边,流量为正无穷(下文解释),费用为fb的

    5.因为每天剩下的毛巾,我们可以不当天洗,所以连接一条从YI到Y(I+1)的边,流量为正无穷,费用为0(所以每天可以洗

    的毛巾的个数是可能会很多的,4,5建的边流量要是正无穷)

    6.那么我们每天买的毛巾除了洗,还可以不洗,也就是直接扔掉,所以连一条XI到T的边,流量为need[i],费用为0

    /**************************************************************
        Problem: 1221
        User: BLADEVIL
        Language: Pascal
        Result: Accepted
        Time:1952 ms
        Memory:8120 kb
    ****************************************************************/
     
    //By BLADEVIL
    var
        n, a, b, f, fa, fb  :longint;
        need                :array[0..1010] of longint;
        pre, other,len      :array[0..500010] of longint;
        cost                :array[0..500010] of longint;
        last                :array[0..4010] of longint;
        ss, tt              :longint;
        que                 :array[0..5000] of longint;
        dis                 :array[0..5000] of longint;
        flag                :array[0..5000] of boolean;
        father              :array[0..5000] of longint;
        ans                 :int64;
        l                   :longint;
          
    function min(a,b:longint):longint;
    begin
        if a>b then min:=b else min:=a;
    end;
          
    procedure connect(a,b,c,d:longint);
    begin
        inc(l);
        pre[l]:=last[a];
        last[a]:=l;
        other[l]:=b;
        len[l]:=c;
        cost[l]:=d;
    end;
          
    procedure init;
    var
        i                   :longint;
        use                 :longint;
    begin
        read(n,a,b,f,fa,fb);
        for i:=1 to n do read(need[i]);
        l:=1;
        ss:=2*n+1;
        tt:=2*n+2;
        for i:=1 to n do
        begin
            connect(ss,2*i-1,maxlongint,f);
            connect(2*i-1,ss,0,-f);
            connect(2*i-1,tt,need[i],0);
            connect(tt,2*i-1,0,0);
            connect(ss,2*i,need[i],0);
            connect(2*i,ss,0,0);
            use:=i+a+1;
            if use<=n then
            begin
                use:=use*2-1;
                connect(2*i,use,maxlongint,fa);
                connect(use,2*i,0,-fa);
            end;
            use:=i+b+1;
            if use<=n then
            begin
                use:=use*2-1;
                connect(2*i,use,maxlongint,fb);
                connect(use,2*i,0,-fb);
            end;
        end;
        for i:=1 to n-1 do
        begin
            connect(2*i,2*i+2,maxlongint,0);
            connect(2*i+2,2*i,0,0);
        end;
    end;
      
    function spfa:boolean;
    var
        q, p, cur               :longint;
        h, t                    :longint;
    begin
        filldword(dis,sizeof(dis) div 4,maxlongint div 10);
        que[1]:=ss;
        dis[ss]:=0;
        h:=0; t:=1;
        while t<>h do
        begin
            h:=h mod 5000+1;
            cur:=que[h];
            flag[cur]:=false;
            q:=last[cur];
            while q<>0 do
            begin
                p:=other[q];
                if len[q]>0 then
                begin
                    if dis[p]>dis[cur]+cost[q] then
                    begin
                        father[p]:=q;
                        dis[p]:=dis[cur]+cost[q];
                        if not flag[p] then
                        begin
                            t:=t mod 5000+1;
                            que[t]:=p;
                            flag[p]:=true;
                        end;
                    end;
                end;
                q:=pre[q];
            end;
        end;
        if dis[tt]=maxlongint div 10 then exit(false) else exit(true);
    end;
      
    procedure update;
    var
        cur                     :longint;
        low                     :longint;
       
    begin
        low:=maxlongint div 10;
        cur:=tt;
        while cur<>ss do
        begin
            low:=min(low,len[father[cur]]);
            cur:=other[father[cur] xor 1];
        end;
        cur:=tt;
        while cur<>ss do
        begin
            dec(len[father[cur]],low);
            inc(len[father[cur] xor 1],low);
            inc(ans,low*cost[father[cur]]);
            cur:=other[father[cur] xor 1]; 
        end;
    end;
      
    procedure main;
    begin
        while spfa do update;
        writeln(ans);
    end;
      
    begin
        init;
        main;
    end.
  • 相关阅读:
    红黑树在不同场景的应用及其优势
    微信抢红包简单实现(随机分配金额、并发控制)
    日志采集常见组件优劣势
    LayUIAdminPro使用
    DevExpress中Text和EditValue封装数据示例
    NPOI读取Excel日期类型单元格返回一串数字问题(2020-08-15 变成 12-5月-2020了)
    Win 10 64位 注册 Grid++ Report 控件
    C# EF 读取App.config连接字符串
    EF 用到的两个类
    Jason实现DataTable和List互转
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3470508.html
Copyright © 2011-2022 走看看