最大流SAP算法的当前弧优化

找了很多资料和程序,大多是编程风格和语言实在和我的不相符和。终于搞得有点明白了。因为找的时候会有很多不可行的弧,在距离标号修改之前还是不可行的,那么我们引入cur数组,标志可行的第一条弧,每次如果修改了距离标号的话就修改它。据这位说:"早就听说当前弧优化,但是一加到自己代码上就错。这次终于找到原因了,因为以前把更新距离标号的一部分操作挪到寻找可行弧时完成,但这样一来就会出现问题。把操作独立出来之后问题就解决了。"并且另外一位大牛的程序似乎也是这样的。于是懒惰的我就没有继续思考了,就把这个思路整合到自己的代码里,提交了一道裸的最大流,AC了,程序应该没问题吧。

参考:

http://baike.dangzhi.com/wiki/SAP#SAP.E7.AE.97.E6.B3.95

http://hi.baidu.com/lemon_workshop/blog/item/ab28ecbc71717d0718d81f15.html

http://dementrock.ixiezi.com/2010/07/28/noi-2006-%E6%9C%80%E5%A4%A7%E8%8E%B7%E5%88%A9/

 

 

我想应该很少有题目能卡SAP+GAP+CUR的程序了吧……

附:我的RQNOJ194程序

const
  oo=19930508;
var
  c:array[0..1000,0..1000] of longint;
  h,vh,cur:Array[0..1000] of longint;
  maxflow,n,m,i,j,k,x,y,z:longint;



function aug(i,now:longint):longint;
var
  k,minh,tmp,j:longint;
begin
  aug:=0;
  minh:=n-1;
  if i=n then
  begin
    inc(maxflow,now);
    exit(now);
  end;
  for j:=1 to n do
    if c[i,j]>0 then
    begin
      if h[j]=h[i]-1 then
      begin
        if c[i,j]>now then
          tmp:=aug(j,now)
        else tmp:=aug(j,c[i,j]);
        dec(c[i,j],tmp);
        inc(c[j,i],tmp);
        dec(now,tmp);
        inc(aug,tmp);
        if h[1]>=n then exit;
        if now=0 then break;
      end;
    end;
  if aug=0 then
  begin
    for j:=1 to n do
      if (c[i,j]>0) and (h[j]<minh) then
      begin
        minh:=h[j];
        k:=j;
      end;
    cur[i]:=k;//cur优化
    dec(vh[h[i]]);
    if vh[h[i]]<=0 then h[1]:=n;
    h[i]:=minh+1;
    inc(vh[h[i]]);
  end;
end;

procedure sap;
begin
  fillchar(vh,sizeof(vh),0);
  fillchar(h,sizeof(h),0);
  vh[0]:=n;
  for i:=1 to n do
    cur[i]:=1;//初始化当前弧
  while h[1]<n do
    aug(1,oo);
end;

begin
  readln(m,n);
  for i:=1 to m do
  begin
    readln(x,y,z);
    c[x,y]:=z;
  end;
  sap;
  writeln(maxflow);
end.

posted on 2011-06-05 11:19  oa414  阅读(1309)  评论(0编辑  收藏  举报

导航