bzoj 1059 二分图匹配

题意:我们有一个n*n的黑白(随意) 方阵,1表示黑色 0表示白色,我们可以选择任意两行进行交换 或 任意选择两列进行交换 ,使得方阵的主对角线均为黑色 ,判断局面是否有解

.....这他喵的是二分图匹配....

我们发现,对于同一行的多个1,无论如何我们也不能把它们同时移动到主对角线上(因为它们一定会在同一行,而同一行只有(i,i)能做出贡献),同理,对于同一列上的多个1我们也不能把它们同时移动到主对角线上

得出结论:在同一行或者同一列的1有且只能有1个动到主对角线上。

        即只有不在同一行同一列的两个1我们才能将其都移动到主对角线上。

那么我们就需要找出n个两两不同行且不同列的1使得局面有解,否则无解

是不是有点像去掉对角线条件的八皇后?

然而只是有点像并不能借鉴其搜索的方法,因为我们可以改变我们已有的配对(让(i,j)的1到主对角线上的(x,x)位置)使尽量多的的1在主对角线上

是不是和匈牙利算法很像?没错,就是它~

====================我是理想与现实的分界线_(:з」∠)_======================

我们构造一张二分图,图的一边是行,另一边是列,对于每个黑点连边,二分图匹配即可

var
        t,n             :longint;
        i,j             :longint;
        f               :boolean;
        map             :array[0..210,0..210] of integer;
        link            :array[0..210] of longint;
        flag            :array[0..210] of boolean;

function find(x:longint):boolean;
var
        i,j:longint;
begin
   for i:=1 to n do
   begin
      if (map[x,i]=1) and (not flag[i]) then
      begin
         flag[i]:=true;
         if (link[i]=0) or (find(link[i])) then
         begin
            link[i]:=x;
            exit(true);
         end;
      end;
   end;
   exit(false);
end;

begin
   read(t);
   while (t>0) do
   begin
      dec(t);
      fillchar(link,sizeof(link),0);
      read(n);
      f:=true;
      for i:=1 to n do
       for j:=1 to n do read(map[i,j]);
       //
      for i:=1 to n do
      begin
         fillchar(flag,sizeof(flag),false);
         if not find(i) then
         begin
            f:=false;break;
         end;
      end;
      //
      if f then writeln('Yes') else writeln('No');
   end;
end.
——by Eirlys

bzoj 1059 二分图匹配_第1张图片bzoj 1059 二分图匹配_第2张图片bzoj 1059 二分图匹配_第3张图片bzoj 1059 二分图匹配_第4张图片bzoj 1059 二分图匹配_第5张图片bzoj 1059 二分图匹配_第6张图片bzoj 1059 二分图匹配_第7张图片bzoj 1059 二分图匹配_第8张图片
bzoj 1059 二分图匹配_第9张图片bzoj 1059 二分图匹配_第10张图片



你可能感兴趣的:(贪心,二分图匹配,bzoj)