经典网络流基础题,刚刚接触网络流的同学可以体会一下网络流的魅力。
推荐学习网络流的教材:向期中向总等湖南金牌教练们主编的《奥赛经典·提高篇》
给出关键部分伪代码来介绍一下网络流的标号法:
Repeat
队列置空;
所有点设为未标号;
将源点加入队列,并标号为(0,+∞);
while 队列非空
{
头指针+1
依次检查与头指针指向的元素相连的边
if 另一点没有标号 and 流量可改进
{
尾指针+1,该点入队
a[另一点]<-队列头指针元素
b[另一点]<-Min{b[头指针元素],边的最大流量};
}
}
if 汇点已标号
{
从汇点出发依次修改各条边的流量
}
Until 汇点未标号;
答案<-所有与汇点相连的边的流量
本题的代码:
Program POJ1273;//By_Poetshy
Const
maxn=205;
Var
h,t :Longint;
i,j,k,m,n,ans,p :Longint;
c,f :Array[0..maxn,0..maxn]of Longint;
a,b,seq :Array[0..maxn]of Longint;
v :Array[0..maxn]of Boolean;
Function Min(i,j:Longint):Longint;
begin
if i<j then exit(i);exit(j);
end;
BEGIN
while not eof do
begin
fillchar(c,sizeof(c),0);
fillchar(f,sizeof(f),0);
ans:=0;
readln(n,m);
for i:=1 to n do
begin
readln(j,k,p);
inc(c[j,k],p);
end;
repeat
fillchar(v,sizeof(v),0);
h:=0;t:=1;seq[1]:=1;v[1]:=true;
a[1]:=0;b[1]:=maxlongint;
while h<t do
begin
inc(h);i:=seq[h];
for j:=1 to m do
if (c[i,j]>0)and(f[i,j]<c[i,j])and(not v[j])then
begin
inc(t);seq[t]:=j;
v[j]:=true;
a[j]:=i;b[j]:=min(c[i,j]-f[i,j],b[i]);
end else if (c[j,i]>0)and(f[j,i]>0)and(not v[j])then
begin
inc(t);seq[t]:=j;v[j]:=true;
a[j]:=i;b[j]:=min(f[j,i],b[i]);
end;
if v[m] then break;
end;
if v[m] then
begin
i:=m;
while i<>0 do
begin
if a[i]<>0 then inc(f[a[i],i],b[m]);
i:=a[i];
end;
end;
until not v[m];
for i:=1 to m-1 do
inc(ans,f[i,m]);
writeln(ans);
end;
END.