BZOJ 1059: [ZJOI2007]矩阵游戏 二分图匹配

    怎么说,先引用一下别人的博客吧!(我觉得它很好地反映了我看到这道题后的思路)

 

的确,如果只判断每一行,每一列是否都至少有一个1,行和每一列都至少有一个1,会WA掉的。后来无奈之下看了题解,是二分图匹配,(然而蒟蒻还不懂,去请教了一下czl,经过教导之后终于懂了)。大致是这样的吧!

如果 X 行 Y 列 有一个 黑格子 ,就在 x 和 y 之间连边(x是指行,y是指列,两者是在二分图的两边的), 然后,我们可以把变换看作交换 X 中的点(不改变它们连边的情况,简单地说,比如交换A和B,如果之前A有一条边连向C,那么交换后A仍有一条边连向C), 使得最后每一个xi 都有一条边连向 y, 这其实就是一个二分图最大匹配的问题。 加油,多学多思考。看了其他人一些有关二分图的题,大多都体现出了一个一一对应的关系,在这里,一一对应的关系可以表现为 如果一开始的两个格子在同一行,那么它们之间就将始终在同一行,那么它们之间就这能有一个去填充这一行的主对角线, 即每一行中只能有一个去填充主对角线。 同理,列也是一样的。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<vector>
  5 #include<queue>
  6 #define clr(x,y) memset(x,y,sizeof(x))
  7 #define rep(i,j,k) for(int i = j; i <= k; i++)
  8 #define maxn 205
  9 using namespace std;
 10  
 11 int read()
 12 {
 13     int s = 0, t =1; char c = getchar();
 14     while( !isdigit(c) ){
 15         if( c == '-' ) t = -1; c = getchar();
 16     }
 17     while( isdigit(c) ){
 18         s = s * 10 + c -'0'; c = getchar();
 19     }
 20     return s * t;
 21 }
 22  
 23 int mx[maxn], my[maxn], dx[maxn], dy[maxn], n1, n2;
 24 vector<int> G[maxn]; 
 25 queue<int> q;
 26 bool vis[maxn];
 27  
 28 void clear()
 29 {
 30     while( !q.empty() ) q.pop();
 31     rep(i,0,maxn-1){
 32         G[i].clear();
 33     }
 34 }
 35  
 36 bool match(int x)
 37 {
 38     int s = G[x].size();
 39     rep(i,0,s-1){
 40         int to = G[x][i];
 41         if( !vis[to] && dy[to] == dx[x] + 1 ){
 42             vis[to] = 1;
 43             if( !my[to] || match(my[to]) ){
 44                 my[to] = x; mx[x] =  to;
 45                 return 1;
 46             }
 47         }
 48     }
 49     return 0;
 50 }
 51  
 52 int matching(){
 53     clr(mx,0); clr(my,0);
 54     int ans = 0;
 55     while( true ){
 56         bool flag = 0;
 57         while( !q.empty() ) q.pop();
 58         clr(dx,0); clr(dy,0);
 59         rep(i,1,n1) if( !mx[i] ) q.push(i);
 60         while( !q.empty() ){
 61             int u = q.front(); q.pop();
 62             int s = G[u].size();
 63             rep(i,0,s-1){
 64                 int to = G[u][i];
 65                 if( !dy[to] ) {
 66                     dy[to] = dx[u] + 1;
 67                     if( my[to] ) {
 68                         dx[my[to]] = dy[to] + 1;
 69                         q.push(my[to]);
 70                     } else flag = 1;
 71                 } 
 72             }
 73         }
 74         if( !flag ) break;
 75         clr(vis,0); 
 76         rep(i,1,n1){
 77             if( !mx[i] && match(i) ) ans++; 
 78         }
 79     }
 80     return ans;
 81 }
 82  
 83  
 84 int main()
 85 {
 86     int t = read();
 87     while( t-- ){
 88         clear();
 89         n1 = read(); 
 90         rep(i,1,n1){
 91             rep(j,1,n1){
 92                 if( read() ){
 93                     G[i].push_back(j);
 94                 }
 95             }
 96         }
 97         if( matching() == n1 ) puts("Yes");
 98         else puts("No");
 99     }
100     return 0;
101 }

 

posted on 2016-01-04 13:53  83131  阅读(138)  评论(0编辑  收藏  举报

导航