题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4185
题解:水平和竖直方向;有#相邻,连一条边,求最大匹配。
#include <cstdio>
#include <cstring>
#include <vector>
#define MAXN 602
#define MAXV 1000
using namespace std;
vector<int> mp[MAXN];
int from[MAXV],visited[MAXV];
int matr[MAXN][MAXN];
char gra[MAXN][MAXN];
int match(int x)
{
int i,temp,size;
size=mp[x].size();
for(i=0;i<size;++i)
{
temp=mp[x][i];
if(!visited[temp])
{
visited[temp]=1;
if(from[temp]==-1||match(from[temp]))
{
from[temp]=x;
return 1;
}
}
}
return 0;
}
int hungary(int n)
{
int i,sum=0;
memset(from,-1,sizeof(from));
for(i=0;i<n;++i)
{
memset(visited,0,sizeof(visited));
if(match(i))
++sum;
}
return sum;
}
int main()
{
int n,test,i,j,cnt,cases=0;
scanf("%d",&test);
while(test--)
{
scanf("%d",&n);
cnt=0;
for(i=0;i<n;++i)
{
scanf("%s",gra[i]);
for(j=0;j<n;++j)
{
if(gra[i][j]=='#')
matr[i][j]=cnt++;
}
}
for(i=0;i<=cnt;++i)
{
mp[i].clear();
}
for(i=0;i<n;++i)
{
for(j=0;j<n;++j)
{
if(gra[i][j]!='#')
continue;
if(i>0&&gra[i-1][j]=='#')
mp[matr[i][j]].push_back(matr[i-1][j]);
if(i<n-1&&gra[i+1][j]=='#')
mp[matr[i][j]].push_back(matr[i+1][j]);
if(j>0&&gra[i][j-1]=='#')
mp[matr[i][j]].push_back(matr[i][j-1]);
if(j<n-1&&gra[i][j+1]=='#')
mp[matr[i][j]].push_back(matr[i][j+1]);
}
}
n=cnt;
cnt=hungary(n);
printf("Case %d: %d\n",++cases,cnt/2);
}
return 0;
}