在一张地图中 一个点只可能与上下左右四个点存在关系 符合二分图性质 同时题目规定地图上两个‘#’即可凑成一对 用匈牙利算法解决即可
#include <bits/stdc++.h>
using namespace std;
vector <int> edge[360010];
int mark[610][610];
char mp[610][610];
int clr[360010],match[360010],book[360010];
int n,num;
void build(int x,int y)
{
int next[4][2]={0,-1,-1,0,0,1,1,0};
int i,tx,ty,u,v;
u=mark[x][y];
for(i=0;i<4;i++)
{
tx=x+next[i][0];
ty=y+next[i][1];
if(tx<0||tx>n-1||ty<0||ty>n-1) continue;
if(mark[tx][ty]!=0)
{
v=mark[tx][ty];
edge[u].push_back(v);
}
}
return;
}
void paint(int u)
{
int i,v;
for(i=0;i<edge[u].size();i++)
{
v=edge[u][i];
if(clr[v]==0)
{
clr[v]=3-clr[u];
paint(v);
}
}
return;
}
int dfs(int u)
{
int i,v;
for(i=0;i<edge[u].size();i++)
{
v=edge[u][i];
if(book[v]==0)
{
book[v]=1;
if(match[v]==0||dfs(match[v]))
{
match[v]=u;
match[u]=v;
return 1;
}
}
}
return 0;
}
int main()
{
int t,cas,i,j,ans;
scanf("%d",&t);
cas=1;
while(t--)
{
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%s",mp[i]);
}
memset(mark,0,sizeof(mark));
num=0;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(mp[i][j]=='#')
{
num++;
mark[i][j]=num;
}
}
}
for(i=1;i<=num;i++)
{
edge[i].clear();
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(mp[i][j]=='#')
{
build(i,j);
}
}
}
memset(clr,0,sizeof(clr));
for(i=1;i<=num;i++)
{
if(clr[i]==0)
{
clr[i]=1;
paint(i);
}
}
memset(match,0,sizeof(match));
ans=0;
for(i=1;i<=num;i++)
{
memset(book,0,sizeof(book));
if(clr[i]==2)
{
if(dfs(i)) ans++;
}
}
printf("Case %d: %d\n",cas++,ans);
}
return 0;
}