#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>
#define ll long long
#define LL __int64
#define eps 1e-8
const ll INF=9999999999999;
using namespace std;
#define M 400000100
#define inf 0xfffffff
//vector<pair<int,int> > G;
//typedef pair<int,int> P;
//vector<pair<int,int>> ::iterator iter;
//
//map<ll,int>mp;
//map<ll,int>::iterator p;
char mp[512][112];
int has[512][512];
int marry[512];
bool tempmp[512][512];
int dis[2][4]={0,-1,0,1,1,0,-1,0};
bool vis[512];
int cnt;
void clear()
{
memset(mp,0,sizeof(mp));
memset(has,0,sizeof(has));
memset(marry,-1,sizeof(marry));
memset(tempmp,0,sizeof(tempmp));
cnt=0;
}
bool dfs(int x)
{
for(int i=1;i<=cnt;i++)
{
if(tempmp[x][i] && !vis[i])
{
vis[i]=1;
if(marry[i]==-1 || dfs(marry[i]))
{
marry[i]=x;
return 1;
}
}
}
return 0;
}
int main(void)
{
int n,h,w;
int t;
cin>>t;
while(t--)
{
clear();
scanf("%d %d",&h,&w);
for(int i=1;i<=h;i++)
{
scanf("%s",mp[i]);
for(int j=1;j<=w;j++)
{
if(mp[i][j-1]=='*')
has[i][j]=++cnt;
}
}
for(int i=1;i<=h;i++)
{
for(int j=1;j<=w;j++)
{
if(has[i][j])
{
for(int k=0;k<4;k++)
{
int dx=i+dis[0][k];
int dy=j+dis[1][k];
if(has[dx][dy])
tempmp[has[i][j]][has[dx][dy]]=1;
}
}
}
}
int ans=0;
for(int i=1;i<=cnt;i++)
{
memset(vis,0,sizeof(vis));
if(dfs(i))
ans++;
}
printf("%d\n",cnt-ans/2);//无向二分图的最小路径覆盖 = 顶点数 – 最大二分匹配数/2
}
}
poj3020 Antenna Placement 二分匹配 最小路径覆盖
最新推荐文章于 2021-03-18 10:04:46 发布