/* The Problem of minimum weighted matching in a bipartite graph is obvious in the condition given by the question. The maximum traffic with the minimum cost is used to solve the Connection source point of X sets. The Edge Weight is 1, and the cost is 0 y set connection points, the edge weight is 1, and any element in the 0X connection Y is spent. The Edge Weight is 1, and the minimum cost obtained from the distance between the two Manhattan is the minimum weight matching */# include <stdio. h> # include <iostream> # include <string. h >#include <queue >#include <cmath> using namespace std; const int M = 20010, ME = 100000; const int INF = 0x3f3fffff; struct point {int x, y; point () {} point (const int _ x, const int _ y) {x = _ x, y = _ y;} p1 [51*51], p2 [51*51]; // ****************************** I Nt Head [M], Next [ME], Num [ME], Flow [ME], Cap [ME], Cost [ME], Q [M], inQ [M], Len [M], pre_edge [M]; class MaxFlow {public: void clear () {memset (Head,-1, sizeof (Head )); memset (Flow, 0, sizeof (Flow);} void addedge (int u, int v, int cap, int cost) {Next [top] = Head [u]; num [top] = v; Cap [top] = cap; Cost [top] = cost; Head [u] = top ++; Next [top] = Head [v]; num [top] = u; Cap [top] = 0; Cost [top] =-cost; Head [v] = top ++;} I Nt solve (int s, int t) // return the final cost {int cost = 0; while (SPFA (s, t) {int cur = t, minflow = INF; while (cur! = S) {if (minflow> Cap [pre_edge [cur]-Flow [pre_edge [cur]) minflow = Cap [pre_edge [cur]-Flow [pre_edge [cur]; cur = Num [pre_edge [cur] ^ 1];} cur = t; while (cur! = S) {Flow [pre_edge [cur] + = minflow; Flow [pre_edge [cur] ^ 1]-= minflow; cost + = minflow * Cost [pre_edge [cur]; cur = Num [pre_edge [cur] ^ 1] ;}} return cost;} private: bool SPFA (int s, int t) {fill (Len, Len + M, INF); Len [s] = 0; int head =-1, tail =-1, cur; Q [++ head] = s; while (head! = Tail) {++ tail; if (tail> = M) tail = 0; cur = Q [tail]; for (int I = Head [cur]; I! =-1; I = Next [I]) {if (Cap [I]> Flow [I] & Len [Num [I]> Len [cur] + Cost [I]) {Len [Num [I] = Len [cur] + Cost [I]; pre_edge [Num [I] = I; if (! InQ [Num [I]) {InQ [Num [I] = true; ++ head; if (head> = M) head = 0; Q [head] = Num [I] ;}} InQ [cur] = false;} return Len [t]! = INF;} int top;} my; // ******************************* int n, m; char graph [109] [109]; int main () {while (scanf ("% d", & n, & m), n + m) {my. clear (); for (int I = 0; I <n; I ++) scanf ("% s", graph [I]); int num1 = 1, num2 = 1; for (int I = 0; I <n; I ++) {for (int j = 0; j <m; j ++) {if (graph [I] [j] = 'H') p2 [num2 ++] = point (I, j ); if (graph [I] [j] = 'M') p1 [num1 ++] = point (I, j) ;}} for (int I = 1; I <num1; I ++) {for (int j = 1; j <num2; j ++) {int cost = fabs (p1 [I]. x-p2 [j]. x) + fabs (p1 [I]. y-p2 [j]. y); my. addedge (I, j + num1, 1, cost) ;}} int S = 0, T = num1 + num2; for (int I = 1; I <num1; I ++) my. addedge (S, I, 1, 0); for (int j = 1; j <num2; j ++) my. addedge (j + num1, T, 1, 0); printf ("% d \ n", my. solve (S, T);} return 0 ;}