Files
python/TangDou/AcWing/ErFenTu/POJ3020.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

85 lines
2.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}