zoj1654 Place the Robots 二分图最大匹配
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=654
将每一行的包含空地的区域编号
再将每一列的包含空地的区域编号
然后把每一个横向块看作二部图中顶点的集合x中的顶点
竖向块看作集合y中的顶点,若两个块有公共的空地,则将他们连边
然后就转化为二分图最大匹配问题
代码:
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 7 #define maxn 51 8 int xn,yn; 9 int x[maxn*maxn],y[maxn*maxn]; 10 int xs[maxn][maxn],ys[maxn][maxn]; 11 int m,n; 12 int g[maxn*maxn][maxn*maxn]; 13 int vis[maxn*maxn]; 14 char map[maxn][maxn]; 15 int ans; 16 bool path(int u) 17 { 18 19 for(int v=1;v<=yn;v++) 20 { 21 if(g[u][v] && vis[v]==0) 22 { 23 24 vis[v]=1; 25 if(y[v]==0 || path(y[v])) 26 { 27 x[u]=v; 28 y[v]=u; 29 return 1; 30 } 31 } 32 } 33 return 0; 34 }void MaxMatch() 35 { 36 ans=0; 37 memset(x,0,sizeof(x)); 38 memset(y,0,sizeof(y)); 39 for(int i=1;i<=xn;i++) 40 if(!x[i]) 41 { 42 memset(vis,0,sizeof(vis)); 43 if(path(i)) 44 ans++; 45 46 } 47 printf("%d\n",ans); 48 } 49 int main() 50 { 51 int t; 52 scanf("%d",&t); 53 int iCase=0; 54 while(t--) 55 { 56 printf("Case :%d\n",++iCase); 57 58 59 60 scanf("%d%d",&m,&n); 61 memset(xs,0,sizeof(xs)); 62 memset(ys,0,sizeof(ys)); 63 64 for(int i=0;i<m;i++) 65 scanf("%s",map[i]); 66 67 int num=0; 68 bool flag; 69 for(int i=0;i<m;i++)//对水平方向的块进行编号 70 { 71 flag=0; 72 for(int j=0;j<n;j++) 73 { 74 if(map[i][j]=='o') 75 { 76 if(flag==0) num++; 77 xs[i][j]=num; flag=1; 78 } 79 else if(map[i][j]=='#') flag=0; 80 } 81 } 82 xn=num; 83 num=0; 84 85 for(int j=0;j<n;j++)//对垂直方向的块进行编号 86 { 87 flag=0; 88 for(int i=0;i<m;i++) 89 { 90 if(map[i][j]=='o') 91 { 92 if(flag==0) num++; 93 ys[i][j]=num;flag=1; 94 } 95 else if(map[i][j]=='#') flag=0; 96 } 97 } 98 99 yn=num; 100 101 memset(g,0,sizeof(g)); 102 103 for(int i=0;i<m;i++) 104 { 105 for(int j=0;j<n;j++) 106 { 107 if(xs[i][j]) g[xs[i][j]][ys[i][j]]=1; 108 } 109 } 110 MaxMatch(); 111 112 } 113 return 0; 114 }