bzoj 1059 矩阵游戏

题目大意:

有一个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\n");continue;}
46         else 
47         {
48             for(i=1;i<=n;i++)
49             {
50                 memset(vis,0,sizeof(vis));
51                 if(!find(i)) {printf("No\n");break;}
52             }
53         }
54         if(i==n+1) printf("Yes\n");
55     }
56 }
View Code

 

posted @ 2017-10-10 14:38  jack_yyc  阅读(154)  评论(0编辑  收藏  举报