二分匹配
不难发现,只要发现将黑格子排列一下就能到对角线,那么不论现在图怎样,都一定可以换过去
把黑点看做行列的边,最大匹配即可
//By AcerMo
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=1050;
int match[M],vis[M];
vector<int>v[M];
int map[M][M];
int t,n;
int mid(int x)
{
for (int i=0;i<v[x].size();i++)
{
int go=v[x][i];
if (vis[go]) continue;
vis[go]=1;
if (!match[go]||mid(match[go]))
{
match[go]=x;
return 1;
}
}
return 0;
}
void built()
{
for (int i=1;i<=n;i++)
for (int k=1;k<=n;k++)
if (map[i][k])
v[k].push_back(i);
return ;
}
void clean()
{
fill(vis,vis+n+1,0);
return ;
}
int main()
{
scanf("%d",&t);
while (t--)
{
memset(map,0,sizeof(map));
scanf("%d",&n);
for (int i=1;i<=n;i++)
for (int k=1;k<=n;k++)
scanf("%d",&map[i][k]);
built(); bool flag=0;
for (int i=1;i<=n;clean(),i++)
if (!mid(i)) flag=1;
if (flag) puts("No");
else puts("Yes");
for (int i=1;i<=n;i++)
v[i].clear();
memset(match,0,sizeof(match));
}
return 0;
}