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

来源:互联网 发布:网上找淘宝客服 编辑:程序博客网 时间:2024/05/20 11:48

最天下午又听了一节课,勉强把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.