[POJ] 2226 Muddy Fields(二分图最小点覆盖)

题目地址:http://poj.org/problem?id=2226

二分图的题目关键在于建图。因为“*”的地方只有两种木板覆盖方式:水平或竖直,所以运用这种方式进行二分。首先按行排列,算出每个"*"的序号xi,再按列排序,算出序号yi。

从X集合向Y集合连边。G[xi][yi]=1; 然后就是求二分图的最小顶点覆盖。因为二分图最小点覆盖=最大匹配数。所以匈牙利算法求一下最大匹配就可以了。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<string.h>
  4 #include<algorithm>
  5 #include<math.h>
  6 #include<stdbool.h>
  7 #include<time.h>
  8 #include<stdlib.h>
  9 #include<set>
 10 #include<map>
 11 #include<stack>
 12 #include<queue>
 13 #include<vector>
 14 using namespace std;
 15 #define clr(x,y)    memset(x,y,sizeof(x))
 16 #define sqr(x)      ((x)*(x))
 17 #define rep(i,a,b)  for(int i=(a);i<=(b);i++)
 18 #define LL          long long
 19 #define INF         0x3f3f3f3f
 20 #define A           first
 21 #define B           second
 22 #define PI          acos(-1.0)
 23 const int N=1000+131;
 24 int n,m,k,k1,k2,f[N],g[N][N],c1[N][N],c2[N][N],link[N],flag[N][N];
 25 
 26 void init()
 27 {
 28     clr(f,0);
 29     clr(g,0);
 30     clr(link,-1);
 31     clr(flag,0);
 32     clr(c1,0);
 33     clr(c2,0);
 34     k1=0;k2=0;
 35 }
 36 
 37 bool find(int x)
 38 {
 39     for(int i=1;i<=k2;i++) {
 40         if(!f[i] && g[x][i]) {
 41             f[i]=1;
 42             if(link[i]==-1 || find(link[i])) {
 43                 link[i]=x;
 44                 return true;
 45             }
 46         }
 47     }
 48     
 49     return false;
 50 }
 51 
 52 int hungary()
 53 {
 54     int ans=0;
 55     for(int i=1;i<=k1;i++) {
 56         clr(f,0);
 57         if(find(i)) ans++;
 58     }
 59     return ans;
 60 }
 61 
 62 int main()
 63 {
 64     int u,v;
 65     char a[100];
 66 
 67     init();
 68     scanf("%d%d",&m,&n);
 69     getchar();
 70     for(int i=1;i<=m;i++) {
 71         scanf("%s",a+1);
 72         for(int j=1;j<=n;j++) {
 73             if(a[j]=='*') flag[i][j]=1;
 74         }
 75     }
 76     
 77     for(int i=1;i<=m;i++) {
 78         for(int j=1;j<=n;j++) {
 79             if(!flag[i][j]) continue;
 80             if(!flag[i][j-1]){
 81                 c1[i][j]=++k1;
 82             } else {
 83                 c1[i][j]=k1;
 84             }
 85         }
 86     }
 87     
 88     for(int i=1;i<=n;i++) {
 89         for(int j=1;j<=m;j++) {
 90             if(!flag[j][i]) continue;
 91             if(!flag[j-1][i]) {
 92                 c2[j][i]=++k2;
 93             } else {
 94                 c2[j][i]=k2;
 95             }
 96         }
 97     }
 98     
 99    for(int i=1;i<=m;i++){
100         for(int j=1;j<=n;j++) {
101             g[c1[i][j]][c2[i][j]]=1;
102         }
103    }
104    
105    printf("%d\n",hungary()); 
106     
107     return 0;
108 }

 

posted @ 2015-04-02 16:56  SXISZERO  阅读(211)  评论(0编辑  收藏  举报