[POJ] 3020 Antenna Placement(二分图最大匹配)

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

输入一个字符矩阵,'*'可行,'o'不可行。因为一个点可以和上下左右四个方向的一个可行点组成一个集合,所以对图进行黑白染色(每个点的值为其横纵坐标之和),然后就可划分为二分图,进行最大匹配。最后最大匹配数加剩下的单个点数量即为所求。

  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=2000+131;
 24 const int dx[4]={0,0,-1,1};
 25 const int dy[4]={1,-1,0,0};
 26 int n,m,k,num,k1,k2,f[N],g[N][N],link[N],flag[N][N],b[N],c[N];
 27 char a[N][N];
 28 
 29 void init()
 30 {
 31     clr(f,0);
 32     clr(g,0);
 33     clr(link,-1);
 34     clr(flag,0);
 35     clr(b,0);
 36     clr(c,0);
 37     num=0;
 38     k1=0;
 39     k2=0;
 40 }
 41 
 42 bool find(int x)
 43 {
 44     for(int i=0;i<k2;i++) {
 45         if(!f[c[i]] && g[x][c[i]]) {
 46             f[c[i]]=1;
 47             if(link[c[i]]==-1 || find(link[c[i]])) {
 48                 link[c[i]]=x;
 49                 return true;
 50             }
 51         }
 52     }
 53     
 54     return false;
 55 }
 56 
 57 int hungary()
 58 {
 59     int ans=0;
 60     for(int i=0;i<k1;i++) {
 61         clr(f,0);
 62         if(find(b[i])) ans++;
 63     }
 64     
 65     return ans;
 66 }
 67 
 68 int main()
 69 {
 70     int u,v,cas;
 71     
 72     scanf("%d",&cas);
 73     while(cas--) {
 74         init();
 75         scanf("%d%d",&m,&n);
 76         for(int i=1;i<=m;i++) {
 77             scanf("%s",a[i]+1);
 78             for(int j=1;j<=n;j++) {
 79                 if(a[i][j]=='*') {
 80                     flag[i][j]=1;
 81                     num++;
 82                 }
 83             }
 84         }
 85         
 86         for(int i=1;i<=m;i++) {
 87             for(int j=1;j<=n;j++){
 88                 int p=(i-1)*n+j;
 89                 if((i+j)&1) {
 90                     if(flag[i][j]) b[k1++]=p;
 91                 } else {
 92                     if(flag[i][j]) c[k2++]=p;
 93                 }
 94             }
 95         } 
 96         
 97         for(int i=1;i<=m;i++) {
 98             for(int j=1;j<=n;j++) {
 99                 if(flag[i][j]) {
100                     for(int k=0;k<4;k++) {
101                         int nx=i+dx[k];
102                         int ny=j+dy[k];
103                         if(flag[nx][ny]) {
104                             u=(i-1)*n+j;
105                             v=(nx-1)*n+ny;
106                             g[u][v]=1;
107                         }
108                     }
109                 }
110             }
111         }
112         
113         int ans=hungary();
114         printf("%d\n",ans+num-2*ans);
115         
116         
117     }
118    
119     
120     
121     return 0;
122 }

 

posted @ 2015-04-01 10:17  SXISZERO  阅读(207)  评论(0编辑  收藏  举报