改进过后的匈牙利算法即可轻松秒掉最大流的各种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.