【题解】 [ZJOI2007]矩阵游戏 (二分图匹配)
Solution:
这个二分图藏还是挺深的,重点在哪里呢?首先我们分析下,交换影响的会是哪里。
每一次交换只会影响某一行上的排列或者某一列上的排列,如果有矩阵是下面这样,就一定不会互相影响。
1 0 0 0 0 | 0 0 1 0
0 0 1 0 0 | 1 0 0 0
0 1 0 0 0 | 0 0 0 1
0 0 0 0 1 | 0 1 0 0
0 0 0 1 0 |
所以我们就只用找每一行每一列能不能匹配出一个完美的二分图,若不能就输出No
Code:
1 //It is coded by Ning_Mew on 3.15 2 #include<bits/stdc++.h> 3 4 const int maxn=200+7; 5 6 int T,n,be[maxn]; 7 bool vis[maxn]; 8 int head[maxn],cnt=0; 9 struct Edge{int nxt,to;}edge[maxn*maxn]; 10 11 void add(int from,int to){ 12 edge[++cnt].nxt=head[from]; 13 edge[cnt].to=to; 14 head[from]=cnt; 15 } 16 17 void clear(){ 18 memset(head,0,sizeof(head));cnt=0; 19 memset(be,-1,sizeof(be)); 20 } 21 bool find(int k){ 22 for(int i=head[k];i!=0;i=edge[i].nxt){ 23 int v=edge[i].to; 24 if(!vis[v]){ 25 vis[v]=true; 26 if(be[v]==-1||find(be[v])){be[v]=k;return true;} 27 } 28 } 29 return false; 30 } 31 void work(){ 32 clear(); 33 scanf("%d",&n); 34 for(int i=1;i<=n;i++){ 35 for(int j=1;j<=n;j++){ 36 int box;scanf("%d",&box); 37 if(box){add(j,i);} 38 } 39 } 40 for(int i=1;i<=n;i++){ 41 memset(vis,false,sizeof(vis)); 42 if(find(i)); 43 else {printf("No\n");return;} 44 } 45 printf("Yes\n");return; 46 } 47 int main(){ 48 scanf("%d",&T); 49 for(int i=1;i<=T;i++){work();} 50 return 0; 51 }