pku 3020

建模:

将所有的'*'作为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 ;
}

 

你可能感兴趣的:(pku)