我们首先要推出几点:
一。无论怎么变换,我的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");
}
}