在农夫约翰的农场上,每逢下雨,Bessie最喜欢的三叶草地就积聚了一潭水。这意味着草地被水淹没了,并且小草要继续生长还要花相当长一段时间。因此,农夫约翰修建了一套排水系统来使贝茜的草地免除被大水淹没的烦恼(不用担心,雨水会流向附近的一条小溪)。作为一名一流的技师,农夫约翰已经在每条排水沟的一端安上了控制器,这样他可以控制流入排水沟的水流量。
农夫约翰知道每一条排水沟每分钟可以流过的水量,和排水系统的准确布局(起点为水潭而终点为小溪的一张网)。需要注意的是,有些时候从一处到另一处不只有一条排水沟。
根据这些信息,计算从水潭排水到小溪的最大流量。对于给出的每条排水沟,雨水只能沿着一个方向流动,注意可能会出现雨水环形流动的情形。
第1行: 两个用空格分开的整数N (0 <= N <= 200) 和 M (2 <= M <= 200)。N是农夫John已经挖好的排水沟的数量,M是排水沟交叉点的数量。交点1是水潭,交点M是小溪。
第二行到第N+1行: 每行有三个整数,Si, Ei, 和 Ci。Si 和 Ei (1 <= Si, Ei <= M) 指明排水沟两端的交点,雨水从Si 流向Ei。Ci (0 <= Ci <= 10,000,000)是这条排水沟的最大容量。
输出一个整数,即排水的最大流量。
5 4 1 2 40 1 4 20 2 4 20 2 3 30 3 4 10
50
分析:
模版的dinic算法,找个模版bfsdinic就好了。
代码:
const
maxn=200;
maxm=400;
inf=100000000;
var
v,r,next:array [1..maxm] of longint;
first,now,q,dis:array [1..maxn] of longint;
n,m,x,y,w,i,ans:longint;
procedure addedge(i,x,y,w:longint);
begin
v[i]:=y;
r[i]:=w;
if first[x]<>0 then
next[i]:=first[x];
first[x]:=i;
end;
function check:boolean;
var
head,tail,i,x,y:longint;
begin
for i:=1 to n do
dis[i]:=-1;
head:=0;tail:=1;q[1]:=1;dis[1]:=0;
while head<tail do
begin
inc(head);
x:=q[head];i:=first[x];
while i<>0 do
begin
y:=v[i];
if (r[i]>0) and (dis[y]<0) then
begin
dis[y]:=dis[x]+1;
inc(tail);q[tail]:=y;
if y=n then
exit(true);
end;
i:=next[i];
end;
end;
exit(false);
end;
function try(u,min:longint):longint;
var
i,y,mi:longint;
begin
if u=n then
exit(min);
i:=now[u];
while i<>0 do
begin
y:=v[i];
if (r[i]>0) and (dis[y]=dis[u]+1) then
begin
if r[i]>min then
mi:=min
else
mi:=r[i];
mi:=try(y,mi);
if mi>0 then
begin
dec(r[i],mi);
if i mod 2=1 then
inc(r[i+1],mi)
else
inc(r[i-1],mi);
exit(mi);
end;
end;
i:=next[i];
end;
exit(0);
end;
procedure Dinic;
var
i:longint;
begin
while check do
for i:=1 to 2*m do
now[i]:=first[i];
end;
begin
readln(m,n);
for i:=1 to m do
begin
readln(x,y,w);
addedge(2*i-1,x,y,w);
addedge(2*i,y,x,0);
end;
dinic;
ans:=0;
i:=first[n];
while i<>0 do
begin
ans:=ans+r[i];
i:=next[i];
end;
writeln(ans);
end.