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

78 lines
2.4 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 <bits/stdc++.h>
using namespace std;
const int N = 510, M = N * N * 2;
int dx[] = {0, 0, -1, 1};
int dy[] = {-1, 1, 0, 0};
// 链式前向星
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 st[N], match[N];
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;
}
char g[50][50];
int id[50][50];
int main() {
#ifndef ONLINE_JUDGE
freopen("LightOJ1152.in", "r", stdin);
#endif
int T, n, m, cas = 0;
scanf("%d", &T);
while (T--) {
// 初始化链式前向星
memset(h, -1, sizeof h);
idx = 0;
scanf("%d%d", &n, &m);
// 按char[]数组读入原始地图
for (int i = 1; i <= n; i++) scanf(" %s", g[i] + 1);
// 给每个金子编号,相当于离散化
memset(id, 0, sizeof id);
int cnt = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (g[i][j] == '*') id[i][j] = ++cnt;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (id[i][j]) {
for (int k = 0; k < 4; k++) {
int tx = i + dx[k], ty = j + dy[k];
if (!id[tx][ty]) continue;
if (tx < 1 || tx > n || ty < 1 || ty > m) continue;
add(id[i][j], id[tx][ty]); // 对每个金子,和它四个方向上的金子连边,没有就不连
}
}
int res = 0;
memset(match, -1, sizeof match);
for (int i = 1; i <= cnt; i++) {
memset(st, 0, sizeof st);
if (dfs(i)) res++;
}
/*
*由于对每个金子拆点,求出的最大匹配是双倍的,除以2才是真正的最大匹配,不除以2则是匹配的点,
*那么节点数 - 匹配的点 = 落单的个数。明显落单的金子每个需要一个骨牌,匹配的点两个需要一个骨牌
*于是,答案= 节点 - 匹配点 + 匹配点 / 2
*/
printf("Case %d: %d\n", ++cas, cnt - res / 2);
}
return 0;
}