思路:这道题能用二分图我是完全没有想到的,后来去补了下最大二分图的最大匹配,然后看题解才勉强推了这样的思路
一行的每个元素看成二分图的一边,一列的元素看成二分图的另一边。
如果某个点是1那么就说明从这一行到那一列有一条边。
然后交换某一行对于这一行能够连接到的点并没有关系。
那么对于对角线元素都有一放到二分图里面就是每一列都有一行的元素能够对应,
就相当于二分图的一个最大匹配能不能到n
然后看交换行对匹配肯定没有任何的影响,
那么对于列交换,表面上是交换了行的点能连接的列的点,但是这样也不影响最大值的匹配
那么直接裸匈牙利算法就好了一个。
(左边相当于行,右边相当于列的点,有边相当于有这个位置为1)
代码:
/**
* ┏┓ ┏┓+ +
* ┏┛┻━━━┛┻┓ + +
* ┃ ┃
* ┃ ━ ┃ ++ + + +
* ████━████+
* ◥██◤ ◥██◤ +
* ┃ ┻ ┃
* ┃ ┃ + +
* ┗━┓ ┏━┛
* ┃ ┃ + + + +Code is far away from
* ┃ ┃ + bug with the animal protecting
* ┃ ┗━━━┓ 神兽保佑,代码无bug
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛ + + + +
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛+ + + +
*/
#include<cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include<vector>
#include<queue>
#include<map>
#define sc_int(x) scanf("%d", &x)
#define sc_ll(x) scanf("%lld", &x)
#define pr_ll(x) printf("%lld", x)
#define pr_ll_n(x) printf("%lld\n", x)
#define pr_int_n(x) printf("%d\n", x)
#define ll long long
using namespace std;
const int N=1000000+100;
int n1,n2,m;
ll s[N];
bool st[N];
int macth[N];
int ne[N],h[N],e[N],idx;
void add(int a,int b)
{
ne[idx]=h[a];
e[idx]=b;
h[a]=idx++;
}
bool find(int x)
{
for(int i =h[x] ; i!=-1 ; i=ne[i] )
{
int j=e[i];
if(!st[j])
{
st[j]=true;
if(macth[j]==0||find(macth[j]))
{
macth[j]=x;
return true;
}
}
}
return false;
}
void slove()
{
sc_int(m);
memset(h,-1,sizeof h);
memset(ne,0,sizeof ne);
memset(e,0,sizeof e);
memset(macth,0,sizeof macth);
for(int i =1;i<=m;i++)
{
for(int j =1;j<=m;j++)
{
int x;
cin>>x;
if(x==1)
add(i,j);
}
}
int res=0;
for(int i =1;i<=m;i++)
{
memset(st,0,sizeof st);
if(find(i))res++;
}
if(res==m)
cout<<"Yes\n";
else cout<<"No\n";
}
int main()
{
int t;
sc_int(t);
while(t--)
slove();
return 0;
}