P2604 [ZJOI2010]网络扩容

实话说:

这题是 \(ZJOI\) 的很不正常

此题是贼容易想的,第一问无脑的跑一遍最大流或者费用流,随便你。第二问要求我们把流量变为 \(k+\max flow\) (其中 \(\max flow\) 为上一次的最大流)。我们可以搞一个这样的机制:

  • 我原本有流量 \(flow[i]\),这些流量是不用钱的
  • 我现在要扩充一些,最多扩充到 \(\max longint\),这些流量每一个流需要 \(cost[i]\)

连两次边就好啦...

  • \(add(l[i],r[i],f[i],0);\)
  • \(add(l[i],r[i],maxlongint,c[i]);\)

最后你建立一个第二汇点,让汇点连第二汇点,流量为 \(k+\max flow\) 就好啦。

// luogu-judger-enable-o2
Uses math;

var
    from,reach,next,value,cost:array[-1..50010] of longint;
    dis,pre,last,flow:array[-1..50010] of int64;
    queue:array[-1..50010] of longint;
    cnt:array[-1..8100] of longint;
    vis:array[-1..8100] of boolean;
    l,r,c,f:array[-1..51000] of longint;
    n,m,i,j,k,tot,now,sink,source:longint;
    maxflow,mincost:int64;

procedure add(x,y,sum_1,sum_2:longint);
begin
    inc(tot); from[tot]:=x; reach[tot]:=y; value[tot]:=sum_1; cost[tot]:= sum_2; next[tot]:=cnt[x]; cnt[x]:=tot;
    inc(tot); from[tot]:=y; reach[tot]:=x; value[tot]:=0    ; cost[tot]:=-sum_2; next[tot]:=cnt[y]; cnt[y]:=tot;
end;

function spfa:boolean;
var head,tail,now,i:longint;
begin
    filldword(dis,sizeof(dis) div 4,maxlongint);
    filldword(flow,sizeof(flow) div 4,maxlongint);
    filldword(vis,sizeof(vis) div 4,0);
    head:=1; tail:=1; queue[1]:=source; vis[source]:=True; dis[source]:=0; pre[sink]:=-1;
    while head<=tail do
    begin
        now:=queue[head]; vis[now]:=False; inc(head);
        i:=cnt[now];
        while i<>-1 do
        begin
            if (value[i]>0)and(dis[reach[i]]>dis[now]+cost[i]) then
            begin
                dis[reach[i]]:=dis[now]+cost[i];
                pre[reach[i]]:=now;
                last[reach[i]]:=i;
                flow[reach[i]]:=min(flow[now],value[i]);
                if vis[reach[i]]=False then
                begin
                    vis[reach[i]]:=True;
                    inc(tail); queue[tail]:=reach[i];
                end;
            end;
            i:=next[i];
        end;
    end;
    if pre[sink]=-1 then exit(False); exit(True);
end;

procedure MincostMaxflow;
begin
    maxflow:=0; mincost:=0; now:=0;
    while (spfa) do
    begin
        now:=sink;
        inc(maxflow,flow[sink]);
        inc(mincost,flow[sink]*dis[sink]);
        while now<>source do
        begin
            dec(value[last[now]],flow[sink]);
            inc(value[last[now] xor 1],flow[sink]);
            now:=pre[now];
        end;
    end;
end;

procedure Construction_I;
begin
    filldword(cnt,sizeof(cnt) div 4,maxlongint*2+1); tot:=1;
    fillchar(value,sizeof(value),0);
    fillchar(reach,sizeof(reach),0);
    fillchar(cost,sizeof(cost),0);
    fillchar(next,sizeof(next),0);
    read(n,m,k); source:=1; sink:=n;
    for i:=1 to m do begin read(l[i],r[i],f[i],c[i]); add(l[i],r[i],f[i],0); end;
    MincostMaxflow; write(maxflow,' ');

    filldword(cnt,sizeof(cnt) div 4,maxlongint*2+1); tot:=1;
    fillchar(value,sizeof(value),0);
    fillchar(reach,sizeof(reach),0);
    fillchar(cost,sizeof(cost),0);
    fillchar(next,sizeof(next),0);
   	for i:=1 to m do
    begin
    	add(l[i],r[i],f[i],0);
        add(l[i],r[i],maxlongint,c[i]);
    end;
   	inc(sink); add(sink-1,sink,maxflow+k,0);
   	MincostMaxflow; write(mincost);
end;


begin
    Construction_I;
end.
posted @ 2019-01-25 22:00  _ARFA  阅读(114)  评论(0编辑  收藏  举报