改进过后的匈牙利算法即可轻松秒掉最大流的各种NB算法。不过,这种方法有一个局限,就是右边集合可以匹配多个而左边集合只能匹配一个的时候才可以用,否则只能搞神马SAP等等了。
匈牙利算法的改进:
1、存储右边集合的结果时不要只存一个,而是将所有匹配结果都存下来。
2、在找增广路时,把(res[k]=0)的条件改成(res[k,0]<max[k])
CODE
Program Stead;//By_Thispoet Const maxn=1000; Var pre,other,last :Array[1..maxn*20]of Longint; res :Array[1..20,0..maxn]of Longint; max :Array[1..maxn]of Longint; state :Array[1..20]of Boolean; rank :Array[1..maxn,0..20]of Longint; h,t,i,j,k,n,m,l,r,mid,ans,sum,all :Longint; Function Dfs(i:Longint):Boolean; var j,k,p:Longint; begin j:=last[i]; while j<>0 do begin k:=other[j]; if not state[k] then begin state[k]:=true; if res[k,0]<max[k] then begin inc(res[k,0]); res[k,res[k,0]]:=i; exit(true); end else begin for p:=1 to res[k,0] do if Dfs(res[k,p]) then begin res[k,p]:=i; exit(true); end; end; end; j:=pre[j]; end; exit(false); end; Function Check(pos:Longint):Boolean; begin if m<=pos then exit(true); for h:=1 to m-pos do begin k:=0; fillchar(last,sizeof(last),0); for i:=1 to n do for j:=h to h+pos do begin inc(k);pre[k]:=last[i]; last[i]:=k;other[k]:=rank[i,j]; end; sum:=0; for i:=1 to m do res[i,0]:=0; for i:=1 to n do begin fillchar(state,sizeof(state),0); if Dfs(i) then inc(sum) else break; end; if sum=n then exit(true); end; exit(false); end; BEGIN readln(n,m); for i:=1 to n do for j:=1 to m do read(rank[i,j]); for i:=1 to m do read(max[i]); l:=0;r:=20; all:=0; while l<=r do begin mid:=(l+r)>>1; if check(mid) then begin ans:=mid; r:=mid-1; end else l:=mid+1; end; writeln(ans+1); END.