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
",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
",++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 }
原文地址:https://www.cnblogs.com/xiaozhuyang/p/zoj1654.html