小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏。矩阵游戏在一个N
*N黑白方阵进行(如同国际象棋一般,只是颜色是随意的)。每次可以对该矩阵进行两种操作:行交换操作:选择
矩阵的任意两行,交换这两行(即交换对应格子的颜色)列交换操作:选择矩阵的任意行列,交换这两列(即交换
对应格子的颜色)游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑
色。对于某些关卡,小Q百思不得其解,以致他开始怀疑这些关卡是不是根本就是无解的!!于是小Q决定写一个程
序来判断这些关卡是否有解。
输入
第一行包含一个整数T,表示数据的组数。接下来包含T组数据,每组数据第一行为一个整数N,表示方阵的大
小;接下来N行为一个N*N的01矩阵(0表示白色,1表示黑色)。
输出
输出文件应包含T行。对于每一组数据,如果该关卡有解,输出一行Yes;否则输出一行No。
样例输入
2
2
0 0
0 1
3
0 0 1
0 1 0
1 0 0
样例输出
No
Yes
【数据规模】
对于100%的数据,N ≤ 200
solution:
一看很明显的二分图,但一开始想的不是把每行和列连起来,而是把每个黑点和它所在的行、列的主对角线建边,试了发样例果断放弃。
正解把每个黑点所在的行列相连,只要让每行找到对应列即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int read() { 7 int s=0,f=1; 8 char ch=getchar(); 9 while(ch>‘9‘||ch<‘0‘) { 10 if(ch==‘-‘) { 11 f=-1; 12 } 13 ch=getchar(); 14 } 15 while(ch>=‘0‘&&ch<=‘9‘) { 16 s=(s<<1)+(s<<3)+(ch^48); 17 ch=getchar(); 18 } 19 return s*f; 20 } 21 int single[201][201],result[201],n,T; 22 bool connect[201][201],vis[40001]; 23 bool find(int u) { 24 for(int i=1; i<=n; ++i) { 25 if(connect[u][i]&&!vis[i]) { 26 vis[i]=true; 27 if(!result[i]||find(result[i])) { 28 result[i]=u; 29 return true; 30 } 31 } 32 } 33 return false; 34 } 35 int main() { 36 //freopen("qmatrix.in","r",stdin); 37 //freopen("qmatrix.out","w",stdout); 38 T=read(); 39 while(T--) { 40 n=read(); 41 memset(connect,false,sizeof(connect)); 42 memset(result,0,sizeof(result)); 43 int sum=0; 44 for(int i=1; i<=n; ++i) { 45 for(int j=1; j<=n; ++j) { 46 single[i][j]=read(); 47 if(single[i][j]) { 48 connect[i][j]=1; 49 ++sum; 50 } 51 } 52 } 53 if(sum<n) { 54 printf("No\n"); 55 continue; 56 } 57 int ans=0; 58 for(int i=1; i<=n; ++i) { 59 memset(vis,0,sizeof(vis)); 60 if(find(i)) { 61 ++ans; 62 } 63 } 64 if(ans==n) { 65 printf("Yes\n"); 66 } else { 67 printf("No\n"); 68 } 69 } 70 return 0; 71 }