bzoj 3280: 小R的烦恼 (网络流)

和开发计划一样(数组开太小wa了好多次,然后为什么这么慢?

 

type
  arr=record
    toward,next,cap,cost:longint;
  end;
const
  maxm=200000;
  maxn=300;
var
  edge:array[0..maxm]of arr;
  dist,first,sch,a,new,old,p,slack:array[0..maxn]of longint;
  chose:array[0..maxn]of boolean;
  maxcost,maxflow,n,s,t,tot,esum,i,tt,sum,jj:longint;
 
function min(x,y:longint):longint;
begin
  if x<y then exit(x);
  exit(y);
end;
 
procedure add(i,j,k,l:longint);
begin
  inc(esum);
  edge[esum].toward:=j;
  edge[esum].next:=first[i];
  first[i]:=esum;
  edge[esum].cap:=k;
  edge[esum].cost:=l;
end;
 
procedure addedge(i,j,k,l:longint);
begin
  add(i,j,k,l);
  add(j,i,0,-l);
end;
 
procedure into;
var
  n,m1,m2,i,j,k,cost1,time:longint;
begin
  readln(n,m1,m2);
  fillchar(first,sizeof(first),255);
  esum:=-1;
  for i:=1 to m1 do sch[i]:=i;
  tot:=m1;
  for i:=1 to n do begin
    inc(tot);
    new[i]:=tot;
    inc(tot);
    old[i]:=tot;
  end;
  inc(tot);
  s:=tot;
  inc(tot);
  t:=tot;
  for i:=1 to n do begin
    read(a[i]);
    inc(sum,a[i]);
  end;
  for i:=1 to m1 do begin
    read(j,p[i]);
    addedge(s,sch[i],j,0);
  end;
  for i:=1 to n do begin
    addedge(s,old[i],a[i],0);
    for j:=1 to m1 do
      addedge(sch[j],new[i],a[i],p[j]);
    addedge(new[i],t,a[i],0);
  end;
  for i:=1 to m2 do begin
    read(time,cost1);
    for j:=1 to n-time do
      for k:=j+time+1 to n do
        addedge(old[j],new[k],maxlongint,cost1);
  end;
end;
 
 
function aug(x,flow:longint):longint;
var
  now,more,i,too,value:longint;
begin
  if x=t then begin
    inc(maxflow,flow);
    inc(maxcost,dist[s]*flow);
    exit(flow);
  end;
 // writeln(x);
  i:=first[x];
  chose[x]:=true;
  now:=0;
  while i>=0 do begin
    too:=edge[i].toward;
    value:=edge[i].cost;
    if (edge[i].cap>0) and (not chose[too]) then
      if dist[x]=dist[too]+value then begin
        more:=aug(too,min(edge[i].cap,flow-now));
        dec(edge[i].cap,more);
        inc(edge[i xor 1].cap,more);
        inc(now,more);
        if flow=now then exit(flow);
      end
      else
        slack[too]:=min(slack[too],dist[too]+value-dist[x]);
    i:=edge[i].next;
  end;
  exit(now);
end;
 
function rel:boolean;
var
  i,spent:longint;
begin
  spent:=maxlongint;
  for i:=1 to tot do
    if not chose[i] then spent:=min(spent,slack[i]);
  if spent=maxlongint then exit(false);
  for i:=1 to tot do
    if chose[i] then inc(dist[i],spent);
  exit(true);
end;
 
begin
  readln(tt);
  for jj:=1 to tt do begin
    sum:=0;
    into;
    fillchar(dist,sizeof(dist),0);
    maxcost:=0;
    maxflow:=0;
    repeat
      for i:=1 to tot do slack[i]:=maxlongint;
      repeat
        fillchar(chose,sizeof(chose),false);
      until aug(s,maxlongint)<=0;
    until not rel;
    write('Case ',jj,': ');
    if sum=maxflow then writeln(maxcost)
      else writeln('impossible');
  end;
end.
View Code

 

posted @ 2015-03-22 21:54  Macaulish  阅读(309)  评论(0编辑  收藏  举报