解析:最小路径数=结尾结点数 = n- 非结尾结点数 = n - 最大匹配数。 所以,
最小路径覆盖数 = 结点数 - 最大匹配数。此为有向图。
无向二分图的最小路径覆盖 = 顶点数 – 最大二分匹配数/2
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 600;
int map[N][N];
int e[N][N], line[N];
bool visit[N];
int dir[4][2] = {1, 0, 0, 1, 0, -1, -1, 0};
int n, m;
int find(int x){
for(int i = 1; i <= m; ++i){
if(visit[i] == false && e[x][i]){
visit[i] = true;
if(line[i] == -1 || find(line[i])){
line[i] = x;
return 1;
}
}
}
return 0;
}
int main(){
int t;
scanf("%d", &t);
while(t--){
memset(e, 0, sizeof(e));
memset(map, 0, sizeof(map));
cin >> m >> n;
int cnt = 0;
char c;
for(int i = 1; i <= m; ++i)
for(int j = 1; j <= n; ++j){
cin >> c;
if(c == '*') map[i][j] = ++cnt;
}
for(int i = 1; i <= m; ++i)
for(int j = 1; j <= n; ++j){
if(map[i][j]){
for(int k = 0; k < 4; ++k){
int x = i + dir[k][0];
int y = j + dir[k][1];
if(x > 0 && x <= m && y >0 && y <= n && map[x][y]) e[map[i][j]][map[x][y]] = 1;
}
}
}
m = n = cnt;
int num = 0;
memset(line, -1, sizeof(line));
for(int i = 1; i <= n; ++i){
memset(visit, false, sizeof(visit));
if(find(i)) num++;
}
printf("%d\n", n - num / 2);
}
return 0;
}