小QQ是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏――矩阵游戏。矩阵游戏在一个N \times NN×N黑白方阵进行(如同国际象棋一般,只是颜色是随意的)。每次可以对该矩阵进行两种操作:
行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色)
列交换操作:选择矩阵的任意两列,交换这两列(即交换对应格子的颜色)
游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑色。
对于某些关卡,小QQ百思不得其解,以致他开始怀疑这些关卡是不是根本就是无解的!于是小QQ决定写一个程序来判断这些关卡是否有解。
目标状态要求矩阵的主对角线上的格子均为黑色。
即是(1,1),(2,2),(3,3)......(n,n)皆匹配;
如果原图满足每行和每列都匹配,那么通过交换,一定可以换成上面这种情况。
所以拆行和列跑一个最大二分图匹配,并判断匹配数是否等于n即可。
代码见
#include<bits/stdc++.h> #define re register int #define maxn 200+5 using namespace std; int t,n; int ma[maxn][maxn]; inline int read(){ int x=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')f=-1; ch=getchar(); } while(isdigit(ch)){ x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); } return x*f; } int ans,match[maxn]; bool ed[maxn][maxn],vis[maxn]; bool dfs(int x){ for(re i=1;i<=n;i++) if(!vis[i]&&ed[x][i]){ vis[i]=true; if(!match[i]||dfs(match[i])) { match[i]=x; return true; } } return false; } int main() { ios::sync_with_stdio(false); t=read(); while(t--) { ans=0; memset(match,0,sizeof(match)); memset(ed,false,sizeof(ed)); n=read(); for(re i=1;i<=n;i++) for(re j=1;j<=n;j++) ed[i][j]=read(); for(re i=1;i<=n;i++) { memset(vis,false,sizeof(vis)); ans+=dfs(i); } if(ans==n) cout<<"Yes"<<endl; else cout<<"No"<<endl; } return 0; }