您的位置:首页 > 理论基础 > 计算机网络

bzoj 1877: [SDOI2009]晨跑 (网络流)

2015-03-22 22:02 288 查看
明显拆点费用流;

type
arr=record
toward,next,cap,cost:longint;
end;

const
mm=1<<30;
maxn=1000;
maxm=300000;

var
edge:array[0..maxm]of arr;
first,slack,d:array[0..maxn]of longint;
chose:array[0..maxn]of boolean;
s,t,n,m,tot,esum,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,flow*d[s]);
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 d[x]=d[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],d[too]+value-d[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>=mm then exit(false);
for i:=1 to tot do
if chose[i] then inc(d[i],spent);
exit(true);
end;

procedure into;
var
i,j,k,l:longint;
begin
esum:=-1;
fillchar(first,sizeof(first),255);
readln(n,m);
s:=1;
t:=n<<1;
tot:=t;
for i:=2 to n-1 do
addedge(i<<1-1,i<<1,1,0);
addedge(1,2,maxlongint,0);
addedge(n<<1-1,n<<1,maxlongint,0);
for i:=1 to m do begin
readln(j,k,l);
addedge(j<<1,k<<1-1,1,l);
end;
fillchar(d,sizeof(d),0);
end;

begin
into;
maxcost:=0;
maxflow:=0;
repeat
fillchar(slack,sizeof(slack),$7f);
repeat
fillchar(chose,sizeof(chose),false);
until  aug(s,maxlongint)<=0;
until not rel;
writeln(maxflow,' ',maxcost);
end.


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: