小
Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏。矩阵游戏在一个N*N黑白方阵进行(如同国际象棋一般,只是颜色是随
意的)。每次可以对该矩阵进行两种操作:行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色)列交换操作:选择矩阵的任意行列,交换这两
列(即交换对应格子的颜色)游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑色。对于某些关卡,小Q百思不得其
解,以致他开始怀疑这些关卡是不是根本就是无解的!!于是小Q决定写一个程序来判断这些关卡是否有解。
第一行包含一个整数T,表示数据的组数。接下来包含T组数据,每组数据第一行为一个整数N,表示方阵的大小;接下来N行为一个N*N的01矩阵(0表示白色,1表示黑色)。
输出文件应包含T行。对于每一组数据,如果该关卡有解,输出一行Yes;否则输出一行No。
每一行对应一个X结点,每一列对应一个Y结点,如果格子(i,j)为1,则连边(Xi,Yj)。如果该二分图有完美匹配则有解,因为可以交换行列使满足题目条件,即X1-Y1,X2-Y2,X3-Y3…之间有边,否则无解。
1 #include<cstdio>
2 #include<cstring>
3 #include<vector>
4 using namespace std;
5
6 const int maxn = 1000+10;
7
8 bool T[maxn];
9 int lky[maxn];
10 vector<int> G[maxn];
11
12 bool match(int u) {
13 for(int i=0;i<G[u].size();i++) {
14 int v=G[u][i];
15 if(!T[v]) {
16 T[v]=1;
17 if(!lky[v] || match(lky[v])) {
18 lky[v]=u;
19 return true;
20 }
21 }
22 }
23 return false;
24 }
25
26 int n;
27
28 int main() {
29 //freopen("matrix.in","r",stdin);
30 //freopen("matrix.out","w",stdout);
31 int kase;
32 scanf("%d",&kase);
33 while(kase--) {
34 scanf("%d",&n);
35 for(int i=1;i<=n;i++) G[i].clear();
36 int u,cnt;
37 for(int i=1;i<=n;i++)
38 for(int j=1;j<=n;j++) {
39 scanf("%d",&u);
40 if(u) G[i].push_back(j),cnt++;
41 }
42 if(cnt<n) puts("No");
43 else {
44 memset(lky,0,sizeof(lky));
45 int ans=0;
46 for(int i=1;i<=n;i++) {
47 memset(T,0,sizeof(T));
48 if(match(i)) ans++;
49 }
50 if(ans==n) puts("Yes");
51 else puts("No");
52 }
53 }
54 return 0;
55 }