网络最大流——Ford-Fulkerson和Edmonds-Karp

最天下午又听了一节课,勉强把MaxiumFlow的两个算法写出来了。其实两个算法的不同之处就在于寻找“增广链”的方式——Ford-Fulkerson是随便找一条,我就用了DFS;Edmonds-Karp要求找一条节点数最少的,我用BFS。但就是这样的差别,两个程序的执行效率不可同日而语——Edmonds-Karp可以过100,而Ford-Fulkerson过50时时间就不可忍受了(也许是我找增广链的方式不对,因为Fish大牛的Ford-Fulkerson明显效率比我高)。
    另外,Fish大牛的两个程序都在100+行,而我的两个程序只在80+行(Edmonds-Karp甚至比Ford-Fulkerson少了5行),所以我怀疑我是不是少写点东西,但就目前,我用随机数据测试,跟Fish大牛的Edmonds-Karp结果是一样的。我没有看懂Fish大牛的程序,直接按照MIT课上讲的东西写的。

program ford_fulkerson;
var
  g,gf:array[1..100,1..100] of longint;
  path:array[0..100] of longint;
  inpath:Array[1..100] of boolean;
  n,f,s,t:longint;
  find:boolean;

procedure findpath(s,z:longint);
var
  i:longint;
begin
  for i:=1 to n do begin
    if (gf[s,i]>0) and (not inpath[i]) then begin
      path[z]:=i;
      inpath[i]:=true;
      if i=t then begin
        path[0]:=z;
        find:=true;
        inpath[i]:=false;
        break;
      end;
      findpath(i,z+1);
      inpath[i]:=false;
    end;
    if find then break;
  end;
end;

procedure countf;
var
  i:longint;
begin
  f:=maxint;
  for i:=1 to path[0]-1 do
    if f>gf[path[i],path[i+1]] then f:=gf[path[i],path[i+1]];
end;

procedure maxflow;
var
  i:longint;
begin
  findpath(s,2);
  repeat
    countf;
    for i:=1 to path[0]-1 do begin
      dec(gf[path[i],path[i+1]],f);
      inc(gf[path[i+1],path[i]],f);
    end;
    find:=false;
    findpath(s,2);
  until not find;
end;

procedure buildg;
var
  i,j:longint;
begin
  for i:=1 to n do
    for j:=1 to n do begin
      dec(g[i,j],gf[i,j]);
      if g[i,j]<0 then g[i,j]:=0;
    end;
  j:=0;
  for i:=1 to n do inc(j,g[i,t]);
  writeln(s,'-->',t,': ',j);
end;

procedure init;
var
  i,j:longint;
begin
  readln(n,s,t);
  while not eof do begin
    readln(i,j,g[i,j]);
    gf[i,j]:=g[i,j];
  end;
  path[1]:=s;
  inpath[1]:=true;
end;

begin
  init;
  maxflow;
  buildg;
end.

program edmonds_karp;
var
  g,gf:array[1..100,1..100] of longint;
  q,path,f:array[1..100] of longint;
  inpath:array[1..100] of boolean;
  n,s,t,z:longint;

procedure find;
var
  i,j:longint;
begin
  z:=1; i:=0;
  while (i<z) and (not inpath[t]) do begin
    inc(i);
    for j:=1 to n do
      if (gf[q[i],j]>0) and (not inpath[j]) then begin
        inc(z);
        q[z]:=j;
        inpath[j]:=true;
        path[j]:=q[i];
        f[j]:=f[q[i]];
        if f[j]>gf[q[i],j] then f[j]:=gf[q[i],j];
      end;
  end;
  while (q[z]<>t) and (z>1) do dec(z);
  fillchar(inpath,sizeof(inpath),false);
  inpath[s]:=true;
end;

procedure maxflow;
var
  i:longint;
begin
  find;
  repeat
    i:=q[z];
    while i<>s do begin
      dec(gf[path[i],i],f[q[z]]);
      inc(gf[i,path[i]],f[q[z]]);
      i:=path[i];
    end;
    find;
  until z=1;
end;

procedure buildg;
var
  i,j:longint;
begin
  for i:=1 to n do
    for j:=1 to n do begin
      dec(g[i,j],gf[i,j]);
      if g[i,j]<0 then g[i,j]:=0;
    end;
  j:=0;
  for i:=1 to n do inc(j,g[i,t]);
  writeln(s,'-->',t,': ',j);
end;

procedure init;
var
  i,j:longint;
begin
  readln(n,s,t);
  while not eof do begin
    readln(i,j,g[i,j]);
    gf[i,j]:=g[i,j];
  end;
  f[1]:=maxint;
  q[1]:=s;
  path[1]:=s;
  inpath[1]:=true;
end;

begin
  init;
  maxflow;
  buildg;
end.

 


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值