bzoj 1834最大ストリーム+最小費用最大ストリーム

11635 ワード

テンプレートになりますが...この問題の2番目の質問の構図はやはり考えてみてください...残量ネットワークでは元のエッジをすべて加算しますが、費用wがあり、容量は無限大で、最初のエッジはやはり費用0でソースポイントsを新規作成し、sは1連1辺、容量はk、費用は0で、このエッジが満流であることを保証し、最小の費用があります.
program bzoj1834;
type point=record
        s,t,cap,flow,o,w,next:longint;
end;
var p,l,n,m,k,c,i:longint;
      v1:array[0..1010]of boolean;
      edge:array[1..30010]of point;
      head,d:array[0..1010]of longint;
      b:array[1..10000000]of longint;
      u,v,w:array[0..5010]of longint;
procedure add(u,v,c,w:longint);
begin
 l:=l+1;
 edge[l].s:=u;
 edge[l].t:=v;
 edge[l].cap:=c;
 edge[l].flow:=0;
 edge[l].o:=l+1;
 edge[l].w:=w;//  
 edge[l].next:=head[u];
 head[u]:=l;
 l:=l+1;
 edge[l].s:=v;
 edge[l].t:=u;
 edge[l].cap:=c;
 edge[l].flow:=c;
 edge[l].o:=l-1;
 edge[l].w:=-w;
 edge[l].next:=head[v];
 head[v]:=l;
end;
function min(a,b:longint):longint;
begin
 if a<b then min:=a else min:=b;
end;

function bfs:boolean;
var top,tail,p:longint;
begin
 d[1]:=1;
 top:=1;tail:=1;
 b[1]:=1;
 fillchar(v1,sizeof(v1),false);
 v1[1]:=true;
 repeat
  p:=head[b[top]];
  while p<>-1 do
       begin
         if (v1[edge[p].t]=false)and(edge[p].cap>edge[p].flow) then
              begin
               v1[edge[p].t]:=true;
               d[edge[p].t]:=d[b[top]]+1;//  
               tail:=tail+1;
               b[tail]:=edge[p].t;
              end;
         p:=edge[p].next;
       end;
  top:=top+1;
 until top>tail;
 exit(v1[n]);
end;



function addflow(x,maxflow:longint):longint;
var p,o:longint;
begin
  if (x=n) or (maxflow=0) then exit(maxflow);
  addflow:=0;//      !!
  p:=head[x];
  while p<>-1 do
       begin
         if (d[edge[p].t]=d[x]+1)and(edge[p].cap>edge[p].flow) then
          begin
            o:=addflow(edge[p].t,min(maxflow,edge[p].cap-edge[p].flow));
            if o>0 then
             begin
               inc(edge[p].flow,o);
               dec(edge[edge[p].o].flow,o);
               maxflow:=maxflow-o;
               addflow:=addflow+o;
               if maxflow=0 then break;
             end;
          end;
         p:=edge[p].next;
       end;
end;



function dinic:longint;
begin
 dinic:=0;
 while bfs do
      dinic:=dinic+addflow(1,maxlongint);
end;

function spfa:longint;
var cost,top,tail,i,p:longint;
      pre,re:array[0..1010]of longint;
      flag:array[0..1010]of boolean;
      d:array[0..1010]of longint;
      mm:longint;
begin
 cost:=0;
 while true do
    begin
      top:=1;tail:=1;
      b[1]:=0;
      for i:=0 to n do d[i]:=maxlongint;
      d[0]:=0;//  
      fillchar(pre,sizeof(pre),0);
      pre[0]:=-1;
      fillchar(re,sizeof(re),0);
      fillchar(flag,sizeof(flag),true);
      flag[0]:=false;
      repeat
       p:=head[b[top]];
       while p<>-1 do
         begin
          if (edge[p].cap>edge[p].flow)and(d[b[top]]+edge[p].w<d[edge[p].t]) then
            begin
             d[edge[p].t]:=d[b[top]]+edge[p].w;
             pre[edge[p].t]:=b[top];
             re[edge[p].t]:=p;
             if flag[edge[p].t] then
              begin
                flag[edge[p].t]:=false;
                tail:=tail+1;
                b[tail]:=edge[p].t;
              end;
            end;
          p:=edge[p].next;
         end;
        flag[b[top]]:=true;
        top:=top+1;
      until top>tail;
      if d[n]=maxlongint then break;
      i:=n;
      mm:=maxlongint;
      while pre[i]<>-1 do
        begin
          mm:=min(mm,edge[re[i]].cap-edge[re[i]].flow);
          i:=pre[i];
        end;
      i:=n;
      while pre[i]<>-1 do
        begin
         inc(edge[re[i]].flow,mm);
         dec(edge[edge[re[i]].o].flow,mm);
         cost:=cost+mm*edge[re[i]].w;
         i:=pre[i];
        end;
    end;
  spfa:=cost;
end;
begin
 read(n,m,k);
 for i:=0 to n do head[i]:=-1;
 for i:=1 to m do
     begin
       read(u[i],v[i],c,w[i]);
       add(u[i],v[i],c,0);
     end;
 write(dinic,' ');
 //       
 for i:=1 to m do
    add(u[i],v[i],maxlongint,w[i]);
 add(0,1,k,0);

 writeln(spfa);
 readln;readln;
end.