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

Leohh發表於2018-02-08

題目連結: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 }

 

相關文章