/* **********************************************************************
2分图最佳匹配,用的最小费用流
SPFA求增广路径,倒序追踪更新流,在Edmonds_karp算法的基础上修改。
需要注意结点的编号,man是从1~n,house是n+1~2*n,附加源点和汇点的容量
和权值分别为1和0。
需要注意的细节很多
**********************************************************************
*/
#include
< iostream >
#include
< queue >
using   namespace  std;
queue
< int > q;
bool  flag[ 220 ]; // 标记是否出队
char  m[ 220 ][ 220 ]; // 地图
int  r,c,s,t;
struct  MAP
{
    
int  c,f,w;
}map[
220 ][ 220 ];
int  maxflow,mincost,nm,nh,man[ 101 ][ 2 ],house[ 101 ][ 2 ],v[ 220 ],pre[ 220 ],cost[ 220 ];
// cost[]----费用,pre[]----父节点
void  Init() // 构造网络流
{
    
int  i,j;
    s
= 2 * nh + 2 ,t = 2 * nh + 1 ;
    
for (i = 1 ;i <= nm;i ++ )
    {
        
for (j = 1 ;j <= nh;j ++ )
        {
            map[i][nm
+ j].c = 1 ;
            map[i][nm
+ j].w = abs(man[i][ 0 ] - house[j][ 0 ]) + abs(man[i][ 1 ] - house[j][ 1 ]);
        }
    }
    
for (i = 1 ;i <= nm;i ++ )
    {
        map[s][i].c
= 1 ; // nh+2为附加源点,nh+1为附加汇点
        map[s][i].w = 0 ;
    }
    
for (i = nh + 1 ;i <= 2 * nh;i ++ )
    {
        map[i][t].c
= 1 ;
        map[i][t].w
= 0 ;
    }
    
return  ;
}
bool  spfa()
{
    
int  i,j;
    memset(v,
0 , sizeof (v));
    memset(flag,
0 , sizeof (flag));
    memset(pre,
0 , sizeof (pre));
    
for (i = 1 ;i <= 2 * nh + 2 ;i ++ )
    {
        cost[i]
= INT_MAX;
    }
    
while ( ! q.empty())
        q.pop();
    v[s]
= INT_MAX;
    pre[s]
= s;
    cost[s]
= 0 ;
    flag[s]
= 1 ;
    q.push(s);
    
while ( ! q.empty())
    {
        i
= q.front();
        
for (j = 1 ;j <= 2 * nh + 2 ;j ++ )
        {
            
if (map[i][j].f < map[i][j].c && cost[i] + map[i][j].w < cost[j])
            {
                cost[j]
= cost[i] + map[i][j].w;
                v[j]
= min(v[i],map[i][j].c - map[i][j].f);
                pre[j]
= i;
                
if ( ! flag[j])
                {
                    flag[j]
= 1 ;
                    q.push(j);
                }
            }
            
else   if (map[j][i].f && cost[i] - map[j][i].w < cost[j])
            {
                cost[j]
= cost[i] - map[j][i].w;
                v[j]
= min(v[i],map[j][i].f);
                pre[j]
=- 1 * i;
                
if ( ! flag[j])
                {
                    flag[j]
= 1 ;
                    q.push(j);
                }
            }
        }
        q.pop();
        flag[i]
= 0 ;
    }
    
if (v[t] > 0 )
        
return   1 ;
    
else  
        
return   0 ;
}
int  mcmf()
{
    
int  i,j;
    maxflow
= 0 ,mincost = 0 ;
    
while (spfa())
    {
        j
= t;
        maxflow
+= v[t];
        
while (j != s)
        {
            i
= abs(pre[j]);
            
if (pre[j] > 0 )
            {
                map[i][j].f
+= v[t];
                mincost
+= v[t] * map[i][j].w;
            }
            
else
            {
                map[j][i].f
-= v[t];
                mincost
-= v[t] * map[j][i].w;
            }
            j
= i;
        }
    }
    
return  mincost;
}
int  main()
{
    
int  i,j,k;
    
while (scanf( " %d%d " , & r, & c) != EOF && r && c)
    {
        memset(map,
0 , sizeof (map));
        memset(man,
0 , sizeof (man));
        memset(house,
0 , sizeof (house));
        nm
= nh = 0 ;
        getchar();
        
for (i = 1 ;i <= r;i ++ )
        {
            
for (j = 1 ;j <= c;j ++ )
            {
                scanf(
" %c " , & m[i][j]);
                
if (m[i][j] == ' m ' )
                {
                    man[
++ nm][ 0 ] = i;
                    man[nm][
1 ] = j;
                }
                
else   if (m[i][j] == ' H ' )
                {
                    house[
++ nh][ 0 ] = i;
                    house[nh][
1 ] = j;
                }
            }
            getchar();
        }
        Init();
        printf(
" %d\n " ,mcmf());
    }
    
return   0 ;
}