题目描述

小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


题解

二分图最大匹配

本题和“给你一些黑色格子,问能否选出n个,使得每行、每列有且仅有一个黑色格子”是相同的。

证明:

必要性:假设不能使得每行、每列有且仅有至少一个黑色格子,那么一定存在某行或列不存在黑色格子,无论如何交换,该行或列都不存在黑色格子,故无解。必要性证毕。

充分性:如果存在某种选择方式使得每行、每列都有且仅有一个黑色格子,那么我们只考虑这n个格子,无论如何交换它们的行或列,每行、每列依然都有且仅有一个黑色格子。从1到n考虑,对于第i行,如果该行不合法,那么一定存在i+1~n行的某行中第i列为黑色。此时只需要交换这两列即可。进行到第n行时,由于前n-1行和前n-1列都已经有黑色格子,那么最后一个黑色格子一定存在于第n行第n列。故所有每行、每列有且仅有一个黑色格子的情况均有解。充分性证毕。

于是这道看起来十分复杂的题就变成了经典二分图傻*题,两个集合分别为行和列,黑色节点的行和列之间连边,问最小点覆盖是否为n。转化为最大匹配求即可。

这里为了效率跑了dinic。

#include <cstdio>
#include <cstring>
#include <queue>
#define N 500
#define M 200000
using namespace std;
queue<int> q;
int head[N] , to[M] , val[M] , next[M] , cnt , s , t , dis[N];
void add(int x , int y , int z)
{
to[++cnt] = y , val[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
to[++cnt] = x , val[cnt] = 0 , next[cnt] = head[y] , head[y] = cnt;
}
bool bfs()
{
int x , i;
memset(dis , 0 , sizeof(dis));
while(!q.empty()) q.pop();
dis[s] = 1 , q.push(s);
while(!q.empty())
{
x = q.front() , q.pop();
for(i = head[x] ; i ; i = next[i])
{
if(val[i] && !dis[to[i]])
{
dis[to[i]] = dis[x] + 1;
if(to[i] == t) return 1;
q.push(to[i]);
}
}
}
return 0;
}
int dinic(int x , int low)
{
if(x == t) return low;
int temp = low , i , k;
for(i = head[x] ; i ; i = next[i])
{
if(val[i] && dis[to[i]] == dis[x] + 1)
{
k = dinic(to[i] , min(temp , val[i]));
if(!k) dis[to[i]] = 0;
val[i] -= k , val[i ^ 1] += k;
if(!(temp -= k)) break;
}
}
return low - temp;
}
int main()
{
int T;
scanf("%d" , &T);
while(T -- )
{
int n , i , j , x;
scanf("%d" , &n) , s = 0 , t = 2 * n + 1;
memset(head , 0 , sizeof(head)) , cnt = 1;
for(i = 1 ; i <= n ; i ++ ) add(s , i , 1) , add(i + n , t , 1);
for(i = 1 ; i <= n ; i ++ )
{
for(j = 1 ; j <= n ; j ++ )
{
scanf("%d" , &x);
if(x) add(i , j + n , 1);
}
}
while(bfs()) n -= dinic(s , 1 << 30);
printf("%s\n" , n ? "No" : "Yes");
}
return 0;
}

【bzoj1059】[ZJOI2007]矩阵游戏 二分图最大匹配的更多相关文章

  1. BZOJ 1059 [ZJOI2007]矩阵游戏 (二分图最大匹配)

    1059: [ZJOI2007]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 5281  Solved: 2530[Submit][Stat ...

  2. [bzoj1059] [ZJOI2007] 矩阵游戏 (二分图匹配)

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

  3. BZOJ1059 [ZJOI2007]矩阵游戏 二分图匹配 匈牙利算法

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1059 题意概括 有一个n*n(n<=200)的01矩阵,问你是否可以通过交换整行和整列使得左 ...

  4. [luogu1129 ZJOI2007] 矩阵游戏 (二分图最大匹配)

    传送门 Description Input Output Sample Input 2 2 0 0 0 1 3 0 0 1 0 1 0 1 0 0 Sample Output No Yes HINT ...

  5. BZOJ1059 ZJOI2007 矩阵游戏 【二分图匹配】

    BZOJ1059 ZJOI2007 矩阵游戏 Description 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏--矩阵游戏.矩阵游戏在一个N*N黑白方阵进行(如同国际象棋一 ...

  6. BZOJ [ZJOI2007]矩阵游戏(二分图匹配)

    1059: [ZJOI2007]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 6390  Solved: 3133[Submit][Stat ...

  7. bzoj 1059: [ZJOI2007]矩阵游戏 二分图匹配

    1059: [ZJOI2007]矩阵游戏 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1891  Solved: 919[Submit][Statu ...

  8. [bzoj1059][ZJOI2007]矩阵游戏_二分图最大匹配

    矩阵游戏 bzoj-1059 ZJOI-2007 题目大意:给定一个n*n的棋盘,上面有一些格子被染黑,剩下都是白色.你每次可以交换两列或者两行,问你能否通过一系列操作使得棋盘的主对角线上的格子全是黑 ...

  9. bzoj 1059: [ZJOI2007]矩阵游戏 [二分图][二分图最大匹配]

    Description 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏.矩阵游戏在一个N *N黑白方阵进行(如同国际象棋一般,只是颜色是随意的).每次可以对该矩阵进行 ...

随机推荐

  1. 使用vscode软件运行zebrajs框架小结

    最近在研究使用zebrajs框架,用vscode编辑器进行开发.vsc这个编辑器说起来还是很强大的,就是支持各种系统的多种语言开发.用于前端的话可以直接在编辑器上边调试javascript,就是需要n ...

  2. MFC双缓冲解决图象闪烁[转]

    转载网上找到的一篇双缓冲的文章,很好用.http://www.cnblogs.com/piggger/archive/2009/05/02/1447917.html__________________ ...

  3. Objective-C Composite Objects

    We can create subclass within a class cluster that defines a class that embeds within it an object. ...

  4. JMeter3.2入门使用教程

    JMeter3.2入门使用教程 背景说明 1.1. 背景简介 JMeter是Apache软件基金会下的一个开源项目,纯java开发的应用工具,可以作为进行负载和压力测试的工具来使用.从最开始时被设计成 ...

  5. MySQL检查死锁简介

  6. cocoapods学习

    1.安装 http://stackoverflow.com/questions/16459028/rvm-install-error-running-requirements-osx-port-ins ...

  7. IE6 bug总结

    IE6bug总结: 1.双边距bug产生原因 margin的方向与浮动的方向相同 解决方法: 浮动的元素身上加 display:inline; ---------------------------- ...

  8. Web开发者必须知道的10个jQuery代码片段

    在过去的几年中,jQuery一直是使用最为广泛的JavaScript脚本库.今天我们将为各位Web开发者提供10个最实用的jQuery代码片段,有需要的开发者可以保存起来. 1.检测Internet ...

  9. syslog(),closelog()与openlog()--日志操作函数 (2)

    文章出处:http://blog.chinaunix.net/uid-26583794-id-3166083.html 守护进程日志的实现 syslogd守护进程用于解决守护进程的日志记录问题,而日志 ...

  10. java在线聊天项目 实现基本聊天功能后补充的其他功能详细需求分析 及所需要掌握的Java知识基础 SWT的激活方法,swt开发包下载,及破解激活码

    补充聊天项目功能,做如下需求分析: 梳理项目开发所需的必要Java知识基础 GUI将使用更快速的swt实现 SWT(Standard Widget Toolkit) Standard Widget T ...