MY*****

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.

  

posted on 2011-10-20 07:54  reflec94  阅读(232)  评论(0编辑  收藏  举报

导航