建模:
将所有的'*'作为X集合,边表示两个点相邻,如此建立的二部图,求出的最大匹配,需要进行处理:
我们发现对于已匹配点,都覆盖了两次,还要加上没有匹配到的点。
//rank:47 132K 0MS 2010-06-06 15:55:48
//Type:二分匹配
#include <stdio.h>
#include <string.h>
#define HL 44
#define WL 11
int adj[HL*WL][5];
int mth[HL*WL];
bool used[HL*WL];
char ms[HL][WL];
int flg[HL][WL];
int dir[4][2] = {{0, -1}, {0, 1}, {1, 0}, {-1, 0}};
int n;
bool path(int u)
{
for (int v=1; v<=adj[u][0]; v++) {
int t = adj[u][v];
if (!used[t]) {
used[t] = 1;
if (!mth[t] || path(mth[t])) {
mth[t] = u;
return 1;
}
}
}
return 0;
}
int main()
{
int T, h, w;
int i, j, k;
int match;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &h, &w);
for (i=0; i<h; i++) {
scanf("%s", ms[i]);
}
n = 0;
for (i=0; i<h; i++) {
for (j=0; j<w; j++) {
if (ms[i][j] == '*') {
flg[i][j] = ++n;
}
}
}
memset(adj, 0, sizeof(adj));
for (i=0; i<h; i++) {
for (j=0; j<w; j++) {
if (ms[i][j] == '*') {
for (k=0; k<4; k++) {
int x = i+dir[k][0];
int y = j+dir[k][1];
if (x>=0 && x<h
&& y>=0 && y<w
&& ms[x][y]=='*') {
int f1 = flg[i][j];
int f2 = flg[x][y];
adj[f1][++adj[f1][0]] = f2;
}
}
}
}
}
match = 0;
memset(mth, 0, sizeof(mth));
for (i=1; i<=n; i++) {
memset(used, 0, sizeof(used));
if (path(i)) {
match++;
}
}
printf("%d\n", n-match/2);
}
return 0;
}