题目大意:
有一个01矩阵,可以交换任意两行或两列,问是否能把所有1放在一个对角线上
思路:
首先可以知道,若两个1在一行或一列内,则不论怎么换,他们还在一行或一列内
因此我们的目标是找到n个1,使得他们的行列都不同
此时我们可以用到二分图匹配
把行作为左边的点,列作为右边的点
对于每个一,连接i j
然后求一下最大匹配
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #include<cstdlib> 7 #include<vector> 8 #include<stack> 9 #include<queue> 10 #define ll long long 11 #define inf 2147383611 12 #define MAXN 210 13 #define MOD 14 using namespace std; 15 inline int read() 16 { 17 int x=0,f=1; 18 char ch;ch=getchar(); 19 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 20 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 21 return x*f; 22 } 23 int i,T,n,cnt,lnk[MAXN]; 24 bool map[MAXN][MAXN],vis[MAXN]; 25 bool find(int x) 26 { 27 for(int i=1;i<=n;i++) 28 { 29 if(map[x][i]&&!vis[i]) 30 { 31 vis[i]=1; 32 if(lnk[i]==-1||find(lnk[i])) {lnk[i]=x;return 1;} 33 } 34 } 35 return 0; 36 } 37 int main() 38 { 39 T=read(); 40 while(T--) 41 { 42 memset(lnk,0xff,sizeof(lnk)); 43 n=read(); 44 for(i=1;i<=n;i++) for(int j=1;j<=n;j++) {map[i][j]=(bool)read();cnt+=map[i][j];} 45 if(cnt<n) {printf("No ");continue;} 46 else 47 { 48 for(i=1;i<=n;i++) 49 { 50 memset(vis,0,sizeof(vis)); 51 if(!find(i)) {printf("No ");break;} 52 } 53 } 54 if(i==n+1) printf("Yes "); 55 } 56 }