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 }

 

posted @ 2018-02-08 17:53  Leohh  阅读(182)  评论(0编辑  收藏  举报