题意:N * N的 01 矩阵,可以进行两个操作:①把两行交换;②把两列交换。问能不能经过几次操作,使矩阵从左上都右下的对角线上全是 1。
题解:首先进行行交换,列交换的时候这一行的元素相对位置不会变,就相当于矩阵中是否存在n个横坐标,纵坐标都不相同的点。核心算法 -> 匈牙利算法。
CODE:
/*
Author: JDD
PROG: bzoj1059 矩阵游戏
DATE: 2015.9.24
*/
#include <cstdio>
#include <cstring>
#define REP(i, s, n) for(int i = s; i <= n; i ++)
#define REP_(i, s ,n) for(int i = n; i >= s; i --)
#define MAX_N 205
using namespace std;
int n;
bool map[MAX_N][MAX_N], used[MAX_N];
int L[MAX_N];
void init()
{
scanf("%d", &n);
memset(map, 0, sizeof(map));
REP(i, 1, n) REP(j, 1, n){
int x; scanf("%d", &x);
if(x) map[i][j] = 1;
}
memset(L, 0, sizeof(L));
}
bool find(int x)
{
REP(i, 1, n){
if(map[x][i] && !used[i]){
used[i] = 1;
if(L[i] == 0 || find(L[i])){
L[i] = x;
return 1;
}
}
}
return 0;
}
void doit()
{
REP(i, 1, n){
memset(used, 0, sizeof(used));
if(!find(i)) {
printf("No\n");
return;
}
}
printf("Yes\n");
}
int main()
{
int T; scanf("%d", &T);
while(T --){
init();
doit();
}
return 0;
}