USACO 4.2 草地排水 Drainage Ditches

来源:互联网 发布:江宁区高新园网络问政 编辑:程序博客网 时间:2024/04/28 12:27

题目大意:
有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.
原创粉丝点击