二部图匹配问题,思路大致就是先将空地按照行进行标号,之后再按照列标号,最后把重叠的部分连一条边,在用匈牙利求出最大的匹配数就可以了,主要是建图这一个步骤,图建好了就很简单了;以下是代码:
话说这次的代码是不是很优美呢。。。。。。
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#define MAXN 51
using namespace std;
char inputmap[MAXN][MAXN];
int grap_x[MAXN][MAXN],grap_y[MAXN][MAXN];
int match_x[MAXN*MAXN],match_y[MAXN*MAXN];
int use[MAXN*MAXN],have_path[MAXN*MAXN][MAXN*MAXN];
int n,m;
int num_x,num_y;
void init()
{
memset(grap_x,0,sizeof(grap_x));
memset(grap_y,0,sizeof(grap_y));
memset(have_path,0,sizeof(have_path));
return ;
}
void build_grap()
{
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
if(grap_x[i][j] != 0 && grap_y[i][j] != 0)
{
have_path[grap_x[i][j]][grap_y[i][j]] = 1;
}
}
}
return ;
}
int find_path(int u)
{
for(int v = 1; v <= num_y; v++)
{
if(have_path[u][v] == 1 && !use[v])
{
use[v] = 1;
if(match_y[v] == -1 || find_path(match_y[v]))
{
match_y[v] = u;
match_x[u] = v;
return 1;
}
}
}
return 0;
}
int maxmatch()
{
int res = 0;
memset(match_x,-1,sizeof(match_x));
memset(match_y,-1,sizeof(match_y));
for(int i = 1; i <= num_x; i++)
{
if(match_x[i] == -1)
{
memset(use,0,sizeof(use));
res+= find_path(i);
}
}
return res;
}
int main()
{
int t;
int num_case=1;
int ans,judge;
scanf("%d", &t);
while(t--)
{
scanf("%d%d", &m, &n);
for(int i = 0; i < m; i++) scanf("%s", inputmap[i]);
init();
num_x=0;
for(int i = 0; i < m; i++)
{
judge = 0;
for(int j = 0; j < n; j++)
{
if(inputmap[i][j] == 'o')
{
if(!judge) num_x++;
grap_x[i][j] = num_x;
judge = 1;
}
if(inputmap[i][j] == '#')
{
judge = 0;
}
}
}
num_y=0;
for(int j = 0; j < n; j++)
{
judge = 0;
for(int i = 0; i < m; i++)
{
if(inputmap[i][j] == 'o')
{
if(!judge) num_y++;
grap_y[i][j] = num_y;
judge = 1;
}
if(inputmap[i][j] == '#')
{
judge = 0;
}
}
}
build_grap();
ans = maxmatch();
printf("Case :%d\n",num_case++);
printf("%d\n",ans);
}
return 0;
}