[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 }

 

你可能感兴趣的:(ant)