洛谷P1129 【ZJOI2007】矩阵游戏

原题传送门

题目描述

QQ是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏――矩阵游戏。矩阵游戏在一个N imes NN×N黑白方阵进行(如同国际象棋一般,只是颜色是随意的)。每次可以对该矩阵进行两种操作:

行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色)

列交换操作:选择矩阵的任意两列,交换这两列(即交换对应格子的颜色)

游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑色。

对于某些关卡,小QQ百思不得其解,以致他开始怀疑这些关卡是不是根本就是无解的!于是小QQ决定写一个程序来判断这些关卡是否有解。

输入输出格式

输入格式:

第一行包含一个整数TT,表示数据的组数。

接下来包含TT组数据,每组数据第一行为一个整数NN,表示方阵的大小;接下来NN行为一个N imes NN×N的0101矩阵(00表示白色,11表示黑色)。

输出格式:

包含TT行。对于每一组数据,如果该关卡有解,输出一行YesYes;否则输出一行NoNo。

输入输出样例

输入样例#1: 复制
2
2
0 0
0 1
3
0 0 1
0 1 0
1 0 0
输出样例#1: 复制
No
Yes

说明

对于20\%20%的数据,N ≤ 7N7

对于50\%50%的数据,N ≤ 50N50

对于100\%100%的数据,N ≤ 200N200

题解

前置知识二分图

此题比较有代表性,思维难度较高,建模后代码很简单。

这题的最终目标是要让主对角线上都是黑格,即对于每一个x∈[1,N],满足(x,x)。

于是此时问题就转化为找N个横纵坐标相同的点,于是我们可以这样建模:

我们将行作为左集合,列作为右集合,每个点就是一条边,而交换行就是交换点的顺序

这样一来,我们就很容易发现只要能实现N个匹配,就一定可以通过交换点来达成目标

然后我们就可以运用二分图匹配的模板解决这道题了

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const int INF=1e9+7,MAXN=201,MAXM=MAXN*MAXN;
 5 int T,N;
 6 int head[MAXN],to[MAXM],nxt[MAXM],tp;
 7 inline void add(int x,int y){
 8     nxt[++tp]=head[x];
 9     head[x]=tp;
10     to[tp]=y;
11 }
12 int used[MAXN],match[MAXN];
13 bool dfs(int x){
14     for(int i=head[x];i;i=nxt[i]){
15         if(!used[to[i]]){
16             used[to[i]]=1;
17             if(!match[to[i]]||dfs(match[to[i]])){
18                 match[to[i]]=x;
19                 return 1;
20             }
21         }
22     }
23     return 0;
24 }
25 int main(){
26     scanf("%d",&T);
27     while(T--){
28         scanf("%d",&N);
29         tp=0;
30         memset(head,0,sizeof(head));
31         memset(match,0,sizeof(match));
32         for(int i=1;i<=N;i++){
33             for(int j=1;j<=N;j++){
34                 int ii;
35                 scanf("%d",&ii);
36                 if(ii){
37                     add(i,j);
38                 }
39             }
40         }
41         int flag=1;
42         for(int i=1;i<=N&&flag;i++){
43             memset(used,0,sizeof(used));
44             flag=dfs(i);
45         }
46         if(flag){
47             puts("Yes");
48         }else{
49             puts("No");
50         }
51     }
52     return 0;
53 }
原文地址:https://www.cnblogs.com/guoshaoyang/p/10567021.html