bzoj 1059 [ZJOI2007]矩阵游戏(完美匹配)

1059: [ZJOI2007]矩阵游戏

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2993  Solved: 1451
[Submit][Status][Discuss]

Description

小 Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏。矩阵游戏在一个N*N黑白方阵进行(如同国际象棋一般,只是颜色是随 意的)。每次可以对该矩阵进行两种操作:行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色)列交换操作:选择矩阵的任意行列,交换这两 列(即交换对应格子的颜色)游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑色。对于某些关卡,小Q百思不得其 解,以致他开始怀疑这些关卡是不是根本就是无解的!!于是小Q决定写一个程序来判断这些关卡是否有解。

Input

第一行包含一个整数T,表示数据的组数。接下来包含T组数据,每组数据第一行为一个整数N,表示方阵的大小;接下来N行为一个N*N的01矩阵(0表示白色,1表示黑色)。

Output

输出文件应包含T行。对于每一组数据,如果该关卡有解,输出一行Yes;否则输出一行No。

Sample Input

2
2
0 0
0 1
3
0 0 1
0 1 0
1 0 0

Sample Output

No
Yes
【数据规模】
对于100%的数据,N ≤ 200

HINT

Source

 

 

【思路】

       每一行对应一个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 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值