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.