bzoj 1834 网络流(最大流+费用流)

题意:n个点,m条无向边,每条边有一个容量和扩容费用(容量扩大1的费用),2个询问:(1)不扩容下的1~N最大流 (2)将最大流增加K的最小费用

强行凑出的网络流经典题么 23333

对于第一问,裸跑最大流即可

第二问的建图还是很不错的,

一开始认为,应该重新建边,容量为K,费用是给题目给的。

but,too young too simple,always naive

因为会出现问题:在残留网络中仍有流量,这些流量扩到新的最大流里是不需要费用的

所以,我们在第一问建图时,费用设为0(解决了不需要费用的问题)

然后在跑完第一问后,再重新建边 x -> y 容量为正无穷(表示这条边可以一直扩容) 费用为给定费用

然后再跑费用流

注意:第一问的最大流为ans,要求增加K,但我们重现连新边后所得的最大流 比 (ans+k)大,这肯定不是最优的(因为你扩了不用扩的)。为了保证第二问增加的流量为K,我们可以在1号或n号点加一条边,容量为k 费用为0,用来限流,使增加的不超过k

注意对应数组的范围,mdzz,开小了改了好久

var
        n,m,k,ans,l       :longint;
        z,ss,st           :longint;
        i                 :longint;
        vis               :array[0..1010] of boolean;
        x,y,cc            :array[0..5010] of longint;
        last,que,dis      :array[0..1010] of longint;
        father            :array[0..1010] of longint;
        pre,other,len,c   :array[0..21010] of longint;
function min(a,b:Longint):longint;
begin
   if atl) do
   begin
      h:=h mod 1005+1;
      cur:=que[h];
      vis[cur]:=false;
      q:=last[cur];
      while (q<>0) do
      begin
         p:=other[q];
         if (dis[p]>dis[cur]+c[q]) and (len[q]>0) then
         begin
            dis[p]:=dis[cur]+c[q];
            father[p]:=q;
            if not vis[p] then
            begin
               tl:=tl mod 1005+1;
               que[tl]:=p;
               vis[p]:=true;
            end;
         end;
         q:=pre[q];
      end;
   end;
   if dis[st]=maxlongint div 10 then exit(false) else exit(true);
end;

procedure update;
var
        cur,low:longint;
begin
   low:=maxlongint; cur:=st;
   while (cur<>ss) do
   begin
      low:=min(low,len[father[cur]]);
      cur:=other[father[cur] xor 1];
   end;
   cur:=st;
   while (cur<>ss) do
   begin
      dec(len[father[cur]],low);
      inc(len[father[cur] xor 1],low);
      inc(ans,low*c[father[cur]]);
      cur:=other[father[cur] xor 1];
   end;
end;

function bfs:boolean;
var
        p,q,cur,h,tl:longint;
begin
   fillchar(dis,sizeof(dis),0);
   h:=0; tl:=1; que[1]:=ss; dis[ss]:=1;
   while (h<>tl) do
   begin
      h:=h mod 1005+1;
      cur:=que[h];
      q:=last[cur];
      while (q<>0) do
      begin
         p:=other[q];
         if (dis[p]=0) and (len[q]>0) then
         begin
            dis[p]:=dis[cur]+1;
            tl:=tl mod 1005+1;
            que[tl]:=p;
            if p=st then exit(true);
         end;
         q:=pre[q];
      end;
   end;
   exit(false);
end;

function dinic(x,flow:longint):longint;
var
        p,q,tt,rest:longint;
begin
   if x=st then exit(flow);
   rest:=flow;
   q:=last[x];
   while (q<>0) do
   begin
      p:=other[q];
      if (dis[p]=dis[x]+1) and (len[q]>0) and (rest>0) then
      begin
         tt:=dinic(p,min(len[q],rest));
         dec(len[q],tt);
         dec(rest,tt);
         inc(len[q xor 1],tt);
         if rest=0 then exit(flow);
      end;
      q:=pre[q];
   end;
   if rest=flow then dis[x]:=0;
   exit(flow-rest);
end;

begin
   read(n,m,k);
   ss:=1; st:=n; l:=1;
   for i:=1 to m do
   begin
      read(x[i],y[i],z,cc[i]);
      connect(x[i],y[i],z,0);
      connect(y[i],x[i],0,0);
      //writeln(l);
   end;
   ans:=0;
   while bfs do inc(ans,dinic(ss,maxlongint div 10));
   //
   write(ans,' ');
   for i:=1 to m do
   begin
      connect(x[i],y[i],maxlongint div 10,cc[i]);
      connect(y[i],x[i],0,-cc[i]);
   end;
   ss:=1; st:=n+1;
   connect(n,st,k,0);
   connect(st,n,0,0);
   //
   ans:=0;
   while spfa do update;
   writeln(ans);
end.
——by Eirlys

bzoj 1834 网络流(最大流+费用流)_第1张图片

你可能感兴趣的:(bzoj,网络流)