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.

 

你可能感兴趣的:(软件开发)