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