題目大意:
小Q是一個非常聰明的孩子,除了國際象棋,他還很喜歡玩一個電腦益智遊戲——矩陣遊戲。矩陣遊戲在一個N*N黑白方陣進行(如同國際象棋一般,只是顏色是隨意的)。每次可以對該矩陣進行兩種操作:行交換操作:選擇矩陣的任意兩行,交換這兩行(即交換對應格子的顏色)列交換操作:選擇矩陣的任意行列,交換這兩列(即交換對應格子的顏色)遊戲的目標,即通過若干次操作,使得方陣的主對角線(左上角到右下角的連線)上的格子均爲黑色。對於某些關卡,小Q百思不得其解,以致他開始懷疑這些關卡是不是根本就是無解的!!於是小Q決定寫一個程序來判斷這些關卡是否有解。
解題思路:
經過發現可得,同行或者同列的黑點,經過任意次變換後依然同行或同列。所以題目可轉換爲能不能找到n個互相不同行或不同列的點。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include <map>
#include<vector>
#include<set>
#define LL long long
#define db double
#define EPS 1e-15
#define inf 1e16
#define pa pair<int,int>
using namespace std;
int n;
int link[201],mp[201][201];
bool used[201];
bool dfs(int u){
int v;
for (v=1;v<=n;v++)
if (mp[u][v] && !used[v]){
used[v]=true;
if (link[v]==-1 || dfs(link[v])){
link[v]=u;
return true;
}
}
return false;
}
int hungary(){
int res=0;
int u;
memset(link,-1,sizeof(link));
for (u=1;u<=n;u++){
memset(used,0,sizeof(used));
if (dfs(u)) res++;
}
return res;
}
int main(){
int p;
scanf("%d",&p);
while (p--){
memset(link,0,sizeof(link));
memset(mp,0,sizeof(mp));
scanf("%d",&n);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++){
int x;
scanf("%d",&x);
if (x) mp[i][j]=1;
}
if (hungary()==n) printf("Yes\n");
else printf("No\n");
}
return 0;
}