bzoj1059

我们首先要推出几点:

一。无论怎么变换,我的1的数量不会变化

二。同一行或者同一列的1不可能经过变换然后在对角线上

基于第二点,我们得出每一列最多只能选一个,每一行最多也只能选一个。如果我们选了(i,j)那么,任何处于第i行的1或者第j列的1都不能再选

那么建图:

如果(i,j)上的是1,那么i->j连一条边,最后求一边二分图匹配,看一看是否是完美匹配。

因为当你选了i->j这条边,你就再也不能用i这个点去选边,也不能再用j这个点去选边了

#include<cstdio>
#include<cstdlib>
#include<cstring>
char s[255];
int first[205];
int mat[205];
bool vis[205];
struct mod{int x,y,next;};
mod q[50005];
int len=0;
void ins(int x,int y)
{
 len++;
 q[len].x=x;
 q[len].y=y;
 q[len].next=first[x];
 first[x]=len;
}
bool find(int x)
{
 for (int i=first[x];i!=0;i=q[i].next)  
 {
  int y=q[i].y;
  if (vis[y]==true)continue;
  vis[y]=true;
  if (mat[y]==-1||find(mat[y])==true)
  {
   mat[y]=x;
   return true;
  }
 }
 return false;
}
int main()
{
 int ttt;
 scanf("%d",&ttt);
 while(ttt--)
 {
  int n;
  scanf("%d",&n);
  memset(first,0,sizeof(first));
  len=0;
  for (int i=1;i<=n;i++)
  {
    for (int j=1;j<=n;j++)
    {
     int x;
     scanf("%d",&x);
     if (x==1)
     ins(i,j);
    }
  }
  //for (int k=1;k<=len;k++)
 // printf("k:%d x:%d y:%d\n",k,q[k].x,q[k].y);
   int num=0;
   memset(mat,-1,sizeof(mat));
  for (int i=1;i<=n;i++)
  {
    memset(vis,false,sizeof(vis));
    if (find(i)==true)num++;
    else break;
  }
  if (num==n)printf("Yes\n");
  else printf("No\n");
 }
     
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值