bzoj 2245 费用流

比较裸

源点连人,每个人连自己的工作,工作连汇,然后因为人的费用是

分度的,且是随工作数非降的,所以我们拆边,源点连到每个人s+1条边

容量是每段的件数,费用是愤怒

/**************************************************************
    Problem: 2245
    User: BLADEVIL
    Language: Pascal
    Result: Accepted
    Time:1532 ms
    Memory:8048 kb
****************************************************************/
 
//By BLADEVIL
var
    n, m                                :longint;
    pre, other, len, cost               :array[0..500010] of longint;
    last                                :array[0..610] of longint;
    source, sink                        :longint;
    time                                :array[0..100] of longint;
    ans                                 :int64;
    father, dis, que                    :array[0..610] of longint;
    flag                                :array[0..610] of boolean;
    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, j                                :longint;
    x, y                                :longint;
 
begin
    read(m,n);
    l:=1;
    source:=n+m+2; sink:=source+1;
    for i:=1 to n do
    begin
        read(x);
        connect(m+i,sink,x,0);
        connect(sink,m+i,0,0);
    end;
     
    for i:=1 to m do
        for j:=1 to n do
        begin
            read(x);
            if x=1 then
            begin
                connect(i,j+m,maxlongint div 10,0);
                connect(j+m,i,0,0);
            end;
        end;
     
    for i:=1 to m do
    begin
        read(x);
        for j:=1 to x do read(time[j]);
        time[0]:=0;
        time[x+1]:=maxlongint div 10;
        for j:=1 to x+1 do
        begin
            read(y);
            connect(source,i,time[j]-time[j-1],y);
            connect(i,source,0,-y);
        end;
    end;
end;
 
function spfa:boolean;
var
    h, t, cur                           :longint;
    q, p                                :longint;
begin
    filldword(dis,sizeof(dis) div 4,maxlongint div 10);
    h:=0; t:=1;
    que[1]:=source;
    dis[source]:=0;
    while h<>t do
    begin
        h:=h mod 600+1;
        cur:=que[h];
        flag[cur]:=false;
        q:=last[cur];
        while q<>0 do
        begin
            if len[q]>0 then
            begin
                p:=other[q];
                if dis[p]>dis[cur]+cost[q] then
                begin
                    dis[p]:=dis[cur]+cost[q];
                    father[p]:=q;
                    if not flag[p] then
                    begin
                        t:=t mod 600+1;
                        que[t]:=p;
                        flag[p]:=true;
                    end;
                end;
            end;
            q:=pre[q];
        end;
    end;
    if dis[sink]=maxlongint div 10 then exit(false) else exit(true);
end;
 
procedure update;
var
    low                                 :longint;
    cur                                 :longint;
begin
    cur:=sink;
    low:=maxlongint;
    while cur<>source do
    begin
        low:=min(low,len[father[cur]]);
        cur:=other[father[cur] xor 1];
    end;
    cur:=sink;
    while cur<>source do
    begin
        dec(len[father[cur]],low);
        inc(len[father[cur] xor 1],low);
        ans:=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.
原文地址:https://www.cnblogs.com/BLADEVIL/p/3488688.html