网络流算法模板

通过USACO草地排水学习了一下网络流,终于写好了几个模板。

最大流

BFS求增广路径

简述:通过BFS在网络中找出一条最短增广路径并修改流量(前向弧加可改进量X,后向弧则减去X),当不存在增广路径时得出最大流,时间效率O(nm^2)。

{
ID: qty1272
PROG: ditch
LANG: PASCAL
}
program ditch;
var
  c,f:array[0..200,0..200]of longint;
  path,u:array[0..200]of longint;
  n,i,m,x,y,z,s,t,max:longint;
procedure change(a:longint);
var i,w:longint;
begin
  w:=t;
  repeat
     i:=w; w:=abs(path[i]);
     if path[i]<0 then f[i,w]:=f[i,w]-a;
     if path[i]>0 then f[w,i]:=f[w,i]+a;
  until w=s;
end;
function find:longint;
var i:longint;
begin
  i:=1;
  while (i<=n)and not((path[i]<>0)and(u[i]=0)) do inc(i);
  if i>n then find:=0 else find:=i;
end;
function ford(var a:longint):boolean;
var i,w:longint;
begin
  ford:=true;
  fillchar(path,sizeof(path),0);
  fillchar(u,sizeof(u),0);
  path[s]:=s;
  while path[t]=0 do
  begin
    x:=find;
    if x=0 then exit;
    for i:=1 to n do
      if (path[i]=0)and((c[x,i]<>0)or(c[i,x]<>0)) then
       begin
         if f[x,i]<c[x,i] then path[i]:=x;
         if f[i,x]>0 then path[i]:=-x;
       end;
    u[x]:=1;
  end;
  w:=t;   a:=maxlongint;
  repeat
     i:=w; w:=abs(path[i]);
     if path[i]<0 then x:=f[i,w];
     if path[i]>0 then x:=c[w,i]-f[w,i];
     if x<a then a:=x;
  until w=s;
  ford:=false;
end;
procedure shuchu;
var i:longint;
begin
  max:=0;
  for i:=1 to n do
   if f[i,t]<>0 then max:=max+f[i,t];
  writeln(max);
end;
procedure work;
var x:longint; g:boolean;
begin
  s:=1; t:=n;
  repeat
     g:=ford(x);
     if g then shuchu
      else change(x);
  until g;
end;
begin
  assign(input,‘ditch.in‘);
reset(input);
assign(output,‘ditch.out‘);
rewrite(output);
  readln(m,n);
  for i:=1 to m do
   begin
     readln(x,y,z);
     c[x,y]:=c[x,y]+z;
   end;
  work;
  close(input); close(output);
end. 

dinic算法
简述:先BFS弄出层次图,在利用DFS找增广路径,时间效率O(n^2m)。

{
ID: qty1272
PROG: ditch
LANG: PASCAL
}
program ditch;
var
  c,f:array[0..200,0..200]of longint;
  team,d:array[0..200]of longint;
  g:array[0..200]of boolean;
  n,i,m,x,y,z,s,t,max,sum:longint;
function min(x,y:longint):longint;
begin
  if x<y then min:=x else min:=y;
end;
function bfs:boolean;
var i,u,head,tail:longint;
begin
  fillchar(g,sizeof(g),false);
  fillchar(d,sizeof(d),0);
  head:=0;  tail:=1;
  g[s]:=true; team[1]:=s;
  while head<tail do
   begin
     head:=head+1; u:=team[head];
     for i:=1 to n do
      if (not g[i])and(c[u,i]>f[u,i]) then
       begin
         d[i]:=d[u]+1; g[i]:=true;
         tail:=tail+1; team[tail]:=i;
       end;
   end;
  exit(g[t]);
end;
function dfs(x,flow:longint):longint;
var i,tmp,k:longint;
begin
  tmp:=flow;
  if x=t then exit(flow);
  for i:=1 to n do
   if (c[x,i]>f[x,i])and(d[x]+1=d[i]) then
    begin
      k:=dfs(i,min(c[x,i]-f[x,i],flow));
      f[x,i]:=f[x,i]+k;
      f[i,x]:=f[i,x]-k;
      flow:=flow-k;
    end;
   exit(tmp-flow);
end;
procedure work;
begin
  sum:=0;s:=1; t:=n;
  while bfs do
   begin
     inc(sum,dfs(s,maxlongint));
   end;
  writeln(sum);
end;
begin
  assign(input,‘ditch.in‘);
reset(input);
assign(output,‘ditch.out‘);
rewrite(output);
  readln(m,n);
  for i:=1 to m do
   begin
     readln(x,y,z);
     c[x,y]:=c[x,y]+z;
   end;
  work;
  close(input); close(output);
end. 

令人比较疑惑的是DFS后面几句 flow:=flow-k; exit(tmp-flow); 这分明是返回k的值,但为什么要这么做呢,因为k在前面被DFS赋值了,不能直接返回该值,否则错误。

时间: 2024-10-19 04:53:05

网络流算法模板的相关文章

POJ 1273 Drainage Ditches(网络流dinic算法模板)

POJ 1273给出M条边,N个点,求源点1到汇点N的最大流量. 本文主要就是附上dinic的模板,供以后参考. #include <iostream> #include <stdio.h> #include <algorithm> #include <queue> #include <string.h> /* POJ 1273 dinic算法模板 边是有向的,而且存在重边,且这里重边不是取MAX,而是累加和 */ using namespace

算法模板——sap网络最大流

实现功能:首行输入N,M,S,T,代表这张图N个点,M条边,源点为S,汇点为T:接下来T行输入个边的出发点.终点和权值:输出最大流 原理:sap网络流算法(详见百度百科,个人觉得这个模板已经不错了,虽然本人暂时还未考虑引入邻接表进行优化) 1 var 2 i,j,k,l,m,n,ans,aug,s,t,tmp,jl,mi:longint; 3 flag:boolean; 4 vh,dis,di,his,pre:array[0..10000] of longint; 5 map:array[0..

POJ 1273 Drainage Ditches (网络流Dinic模板)

Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by water for awhile and takes quite a long time to regrow. Thus, Farmer John has built a set of drainage

tarjan算法模板

var {left表示点 root 没离开栈 vis表示点 root 有没有被访问过} i,n,m,now,time,color,top:longint; v:array[0..10001] of record start:longint;end; e:array[0..100001] of record y,next:longint;end; dfn,low,stack,encolor:array[0..10001] of longint; vis,left:array[0..10001] o

prim算法模板

var g:array[1..10,1..10] of longint; d:array[1..10] of longint; f:array[1..10] of boolean; procedure prim; var i,j,k,min:longint; begin fillchar(g,sizeof(g),0); fillchar(f,sizeof(f),0); for i:=1 to n do d[i]:=g[1,i]; f[1]:=true; for i:=2 to n do begi

bellman-ford算法模板

有SPFA模板,bellman-ford模板显然是多余的. var e:array[1..maxe]of record a,b,w:longint;end; { 距源点s距离 } dis:array[1..maxn]of longint; { 前驱 } pre:array[1..maxn]of longint; m,n,s:longint; procedure relax(u,v,w:longint); begin if dis[u]+w<dis[v] then begin dis[v]:=di

Floyd判最小环算法模板

算法思想:如果存在最小环,会在编号最大的点u更新最短路径前找到这个环,发现的方法是,更新最短路径前,遍历i,j点对,一定会发现某对i到j的最短路径长度dis[i][j]+mp[j][u]+mp[u][i] != INF,这时i,j是图中挨着u的两个点,因为在之前最短路更新过程中,u没有参与更新,所以dis[i][j]所表示的路径中不会出现u,如果成立,则一定是一个环.用Floyd算法来实现.但是对于负环此算法失效,因为有负环时,dis[i][j]已经不能保证i到j的路径上不会经过同一个点多次了.

hdu 1711 KMP算法模板题

题意:给你两个串,问你第二个串是从第一个串的什么位置開始全然匹配的? kmp裸题,复杂度O(n+m). 当一个字符串以0为起始下标时.next[i]能够描写叙述为"不为自身的最大首尾反复子串长度". 当发生失配的情况下,j的新值next[j]取决于模式串中T[0 ~ j-1]中前缀和后缀相等部分的长度, 而且next[j]恰好等于这个最大长度. 防止超时.注意一些细节.. 另外:尽量少用strlen.变量记录下来使用比較好,用字符数组而不用string //KMP算法模板题 //hdu

HDU 2544 最短路(我的dijkstra算法模板、SPAFA算法模板)

思路:这道题是基础的最短路径算法,可以拿来试一下自己对3种方法的理解 dijkstra主要是从第一个点开始枚举,每次枚举出当当前最小的路径,然后再以那最小的路径点为起点,求出它到其它未标记点的最短距离 bellman-ford 算法则是假设有向网中有n 个顶点.且不存在负权值回路,从顶点v1 和到顶点v2 如果存在最短路径,则此路径最多有n-1 条边.这是因为如果路径上的边数超过了n-1 条时,必然会重复经过一个顶点,形成回路:而如果这个回路的权值总和为非负时,完全可以去掉这个回路,使得v1到v