bzoj 1059 二分图匹配

25 篇文章 0 订阅
7 篇文章 0 订阅

题意:我们有一个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





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值