解题思路:
相邻的城市连边。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#define LL long long
#define FOR(i, x, y) for(int i=x;i<=y;i++)
using namespace std;
const int MAXN = 500 + 10;
int G[MAXN][MAXN];
int vis[MAXN];
int match[MAXN];
int Hash[MAXN][MAXN];
char s[MAXN][MAXN];
int n, m;
int h, w;
int tot;
int path(int u)
{
for(int v=1;v<=m;v++)
{
if(G[u][v] && !vis[v])
{
vis[v] = 1;
if(match[v] == -1 || path(match[v]))
{
match[v] = u;
return 1;
}
}
}
return 0;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &h, &w);
memset(Hash, 0, sizeof(Hash));
tot = 0;
for(int i=1;i<=h;i++)
{
scanf("%s", s[i] + 1);
for(int j=1;j<=w;j++)
{
if(s[i][j] == '*')
{
Hash[i][j] = ++tot;
}
}
}
memset(G, 0, sizeof(G));
for(int i=1;i<=h;i++)
{
for(int j=1;j<=w;j++)
{
if(s[i][j] == '*')
{
if(i > 1 && s[i-1][j] == '*')
G[Hash[i-1][j]][Hash[i][j]] = 1;
if(i < h && s[i+1][j] == '*')
G[Hash[i+1][j]][Hash[i][j]] = 1;
if(j > 1 && s[i][j-1] == '*')
G[Hash[i][j-1]][Hash[i][j]] = 1;
if(j < w && s[i][j+1] == '*')
G[Hash[i][j+1]][Hash[i][j]] = 1;
}
}
}
n = m = tot;
int res = 0;
memset(match, -1, sizeof(match));
for(int i=1;i<=n;i++)
{
memset(vis, 0, sizeof(vis));
res += path(i);
}
printf("%d\n", tot - res / 2);
}
return 0;
}