You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

85 lines
2.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
#include <cstring>
#include <vector>
#include <stack>
#include <cstdio>
using namespace std;
const int N = 50, M = N * N;
char a[N][N]; // 原始矩阵
// 链式前向星
int e[M], h[N], idx, w[M], ne[M];
void add(int a, int b, int c = 0) {
e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}
int dx[] = {-1, 0, 1, 0}; // 上右下左
int dy[] = {0, 1, 0, -1}; // 上右下左
int n, m; // n行m列
// 匈牙利算法
int st[M], match[M];
int dfs(int u) {
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if (st[v]) continue;
st[v] = 1;
if (match[v] == -1 || dfs(match[v])) {
match[v] = u;
return 1;
}
}
return 0;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("POJ3020.in", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--) {
// 初始化链式前向星
memset(h, -1, sizeof h);
idx = 0;
scanf("%d %d", &n, &m); // n*m的矩阵
for (int i = 1; i <= n; i++) scanf("%s", a[i] + 1); // 使用char[],按行一次读入,快捷!
int cnt = 0; // 城市个数
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
//*--代表城市o--代表空地
// 给城市安装无线网,一个无线网最多可以覆盖两座城市,问覆盖所有城市最少要用多少无线网。
if (a[i][j] == '*') {
cnt++;
// 四周探测
for (int k = 0; k < 4; k++) {
int tx = i + dx[k], ty = j + dy[k];
if (tx < 1 || tx > n || ty < 1 || ty > m) continue;
// 城市到城市建边,无向图,尽量让无线网构建在两个城市上,这样才能省资源,要不一个城市一个无向网太费了
if (a[tx][ty] == '*') add((i - 1) * m + j, (tx - 1) * m + ty);
}
}
}
}
// 匈牙利
memset(match, -1, sizeof match);
int res = 0;
for (int i = 1; i <= n * m; i++) {
memset(st, 0, sizeof st);
if (dfs(i)) res++;
}
// 无向图重复计算然后除以2,就是最大匹配数
printf("%d\n", cnt - res / 2);
}
return 0;
}