poj 2112
分析:二分图多重匹配。
这个东西是第一次遇到,一直以为多重匹配之类的只能用最大流去解决(这个应该是最大流的基本功能),其实稍微修改一下匈牙利算法就可以了。把next设置成边表类型的,往里头放点,超过limit之后再进行find(next[i,k])进行增广。思路非常简单,二分答案判定即可。
代码:
var
b:array[0..250,0..15] of longint;
v:array[0..250] of boolean;
a:array[0..250,0..250] of longint;
i,j,k,m,n,limit,l,r,mid,ans:longint;
function find(x:longint):boolean;
var
i,j:longint;
begin
for i:=1 to n do
if (a[n+x,i]<=mid)and(not v[i]) then
begin
v[i]:=true;
if b[i,0]<limit then
begin
inc(b[i,0]);
b[i,b[i,0]]:=x;
exit(true);
end else
for j:=1 to limit do
if find(b[i,j]) then
begin
b[i,j]:=x;
exit(true);
end;
end;
exit(false);
end;
function ok:boolean;
var
i:longint;
begin
for i:=1 to m do
begin
fillchar(v,sizeof(v),0);
if not find(i) then exit(false);
end;
exit(true);
end;
begin
readln(n,m,limit);
for i:=1 to n+m do
for j:=1 to n+m do
begin
read(a[i,j]);
if a[i,j]=0 then a[i,j]:=maxlongint>>2;
end;
for k:=1 to n+m do
for i:=1 to n+m do
for j:=1 to n+m do
if a[i,j]>a[i,k]+a[k,j] then
a[i,j]:=a[i,k]+a[k,j];
l:=0; r:=20000;
while l<=r do
begin
fillchar(b,sizeof(b),0);
mid:=(l+r)>>1;
if ok then
begin
r:=mid-1;
ans:=mid;
end else l:=mid+1;
end;
writeln(ans);
end.
浙公网安备 33010602011771号