1. 程式人生 > >BZOJ 1059 [ZJOI2007]矩陣遊戲:二分圖匹配

BZOJ 1059 [ZJOI2007]矩陣遊戲:二分圖匹配

turn sin 格子 get 題目 pan == problem ostream

題目鏈接: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 }

BZOJ 1059 [ZJOI2007]矩陣遊戲:二分圖匹配