bzoj 1221: [HNOI2001] 软件开发 (网络流)

注意说如果直接从每天的新的连向旧的,那整个图的最大流还是不变,答案就一直会是Σni*f

 

 

type
  arr=record
    toward,next,cap,cost:longint;
  end;
const
  maxm=3000000;
  maxn=2200;
var
  edge:array[0..maxm]of arr;
  dist,first,slack:array[0..maxn]of longint;
  chose:array[0..maxn]of boolean;
  n,m,s,t,tot,esum,i,maxflow,maxcost: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;
 
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;
  now:=0;
  chose[x]:=true;
  i:=first[x];
  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 now=flow 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;
 
procedure into;
var
  n,timea,timeb,cost1,costa,costb,i,j:longint;
begin
  readln(n,timea,timeb,cost1,costa,costb);
  fillchar(first,sizeof(first),255);
  esum:=-1;
  s:=n<<1+1;
  t:=n<<1+2;
  tot:=t;
  for i:=1 to n do begin
    read(j);
    addedge(s,i,j,cost1);
    addedge(s,i+n,j,0);
    addedge(i,t,j,0);
  end;
  for i:=1 to n do begin
    for j:=i+timea+1 to n do
      addedge(i+n,j,maxlongint,costa);
    for j:=i+timeb+1 to n do
      addedge(i+n,j,maxlongint,costb);
  end;
end;
 
begin
  into;
  repeat
    for i:=1 to tot do slack[i]:=maxlongint;
    repeat
      fillchar(chose,sizeof(chose),false);
    until aug(s,maxlongint)<=0;
  until not rel;
  writeln(maxcost);
  readln;
  readln;
end.
View Code

 

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