题目大意:
有n个点,给出M条边的最大容量,求从点1到点n最多可以运输多少水。
(0 <= N <= 200)
(2 <= M <= 200)
题解:
这题主要的思路就是网络流:
一个比较暴力的Ford-Fulkerson算法
①枚举找到一条能从1走到n的路径,保证路径上的权值全部大于0.
②路径找一个最小值min即限制值去累加到答案上
③把路径上的边,权值减去min,即w(u,v),-min,然后建一条反向边w(v,u),+min。
重复到找不到一条1通往n的边。
因为流的正反向抵消性质(水从u流到v,再从v流回u,其实就是什么都没发生):
就是如果通过反向弧(v,u)的残余流量增加了流量t,其实相当于f(u,v)=f(u,v)-t,按照上面的性质,其实就是
w(v,u)=w(v,u)-t
w(u,v)=w(u,v)+t
反之,通过正向弧(v,u)的残余流量增加了流量t,其实相当于f(u,v)=f(u,v)+t,按照上面的性质,其实就是
w(v,u)=w(v,u)+t
w(u,v)=w(u,v)-t
注意,输入可能给出多个相同边,权值要累加在一起!
var
a:array [0..201,0..201] of longint;
v:array [0..201] of boolean;
d:array [0..201] of longint;
ans,n,m:longint;
procedure init;
var
i,x,y,z:longint;
begin
readln(n,m);
for i:=1 to n do
begin
readln(x,y,z);
a[x,y]:=a[x,y]+z;
end;
end;
function dfs(dep:longint):boolean;
var
i:longint;
begin
if dep=m then exit(true);
for i:=1 to m do
if (v[i]) and (a[dep,i]>0) then
begin
d[i]:=dep;
v[i]:=false;
if dfs(i) then exit(true);
end;
exit(false);
end;
procedure work;
var
min,i:longint;
begin
min:=maxlongint;
i:=m;
while i>1 do
begin
if min>a[d[i],i] then min:=a[d[i],i];
i:=d[i];
end;
ans:=ans+min;
i:=m;
while i>1 do
begin
a[d[i],i]:=a[d[i],i]-min;
a[i,d[i]]:=a[i,d[i]]+min;
i:=d[i];
end;
end;
procedure main;
var
i:longint;
begin
ans:=0;
for i:=2 to m do
begin
d[i]:=0;
v[i]:=true;
end;
d[1]:=0; v[1]:=false;
while dfs(1) do
begin
work;
for i:=1 to m do
begin
v[i]:=true;
d[i]:=0;
end;
v[1]:=false;
d[1]:=0;
end;
writeln(ans);
end;
begin
init;
main;
end.