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.

  

你可能感兴趣的:(poj)