BZOJ 1059 [ZJOI2007]矩阵游戏:二分图匹配
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1059
题意:
给你一个n*n的01矩阵。
你可以任意次地交换某两行或某两列。
问你是否可以让这个矩阵的主对角线(左上角到右下角的连线)上的格子均为黑色。
题解:
可以发现,对于一个格子,无论怎样移动,它原来行(列)上的格子还是在现在的行(列)上。
因为最终目标是将n个黑色格子移到对角线上,所以只要有n个黑色格子的行列均不相同即可。
那么对于每个黑色格子,将行号i向列号j连一条边,然后跑二分图匹配,看匹配数是否等于n即可。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <vector> 5 #define MAX_N 205 6 7 using namespace std; 8 9 int n,t; 10 int vis[MAX_N]; 11 int match[MAX_N]; 12 vector<int> edge[MAX_N]; 13 14 void read() 15 { 16 cin>>n; 17 for(int i=1;i<=n;i++) edge[i].clear(); 18 int x; 19 for(int i=1;i<=n;i++) 20 { 21 for(int j=1;j<=n;j++) 22 { 23 cin>>x; 24 if(x) edge[i].push_back(j); 25 } 26 } 27 } 28 29 bool hungary(int now,int cnt) 30 { 31 for(int i=0;i<edge[now].size();i++) 32 { 33 int temp=edge[now][i]; 34 if(vis[temp]!=cnt) 35 { 36 vis[temp]=cnt; 37 if(match[temp]==-1 || hungary(match[temp],cnt)) 38 { 39 match[temp]=now; 40 return true; 41 } 42 } 43 } 44 return false; 45 } 46 47 void work() 48 { 49 memset(vis,0,sizeof(vis)); 50 memset(match,-1,sizeof(match)); 51 for(int i=1;i<=n;i++) 52 { 53 if(!hungary(i,i)) 54 { 55 cout<<"No"<<endl; 56 return; 57 } 58 } 59 cout<<"Yes"<<endl; 60 } 61 62 int main() 63 { 64 cin>>t; 65 while(t--) 66 { 67 read(); 68 work(); 69 } 70 }