题目大意:
有一个(n*n)的棋盘,格子有黑白两种颜色,现在可以任意交换两行或列,问能否令主对角线上的格子全部为黑色
(nle 200)
二分图简单套路,将每行看作左部节点,没列看作右部节点,对于每个黑色格点,所在行向所在列连边,跑匈牙利
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
namespace red{
#define int long long
#define mid ((l+r)>>1)
inline int read()
{
int x=0;char ch,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') f=0,ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
}
const int N=410,E=N*N;
int haku;
int n,ret;
bool vis[N];
int f[N];
int head[N],cnt;
struct point
{
int nxt,to;
point(){}
point(const int &nxt,const int &to):nxt(nxt),to(to){}
}a[E];
inline void link(int x,int y)
{
a[++cnt]=(point){head[x],y};head[x]=cnt;
a[++cnt]=(point){head[y],x};head[y]=cnt;
}
inline bool find(int x)
{
for(int i=head[x];i;i=a[i].nxt)
{
int t=a[i].to;
if(vis[t]) continue;
vis[t]=1;
if(!f[t]||find(f[t]))
{
f[t]=x;
return 1;
}
}
return 0;
}
inline void main()
{
haku=read();
while(haku--)
{
memset(head,0,sizeof(head));
memset(f,0,sizeof(f));
memset(a,0,sizeof(a));
cnt=ret=0;
n=read();
for(int x,i=1;i<=n;++i)
{
for(int j=1;j<=n;++j)
{
x=read();
if(x) link(i,j+n);
}
}
for(int i=1;i<=n;++i)
{
memset(vis,0,sizeof(vis));
if(find(i)) ++ret;
}
puts(ret>=n?"Yes":"No");
}
}
}
signed main()
{
red::main();
return 0;
}
/*
1
3
1 1 1
0 0 1
0 0 1
*/