1.建立源点 S与所有的人连 ,流量为1,费用为0。
2.建立汇点 T与所有的房子连,流量为1,费用为0。
之后遍历每个人,然后加边,每个人与每个房子连,流量为1,费用为两个点为曼哈顿距离。
#include<bits/stdc++.h>
#include<vector>
using namespace std;
#define LL long long
#define fread() freopen("in.txt","r",stdin)
#define fwrite() freopen("out.txt","w",stdout)
#define CLOSE() ios_base::sync_with_stdio(false)
const int maxn = 10000+10;
const int maxm = 100+10;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
struct Edge
{
int from,to,next,cap,flow,cost;
}edge[maxn*10];
int head[maxn],top;
void init()
{
memset(head,-1,sizeof(head));
top = 0;
}
void addege(int a,int b,int w,int c)
{
edge[top].from = a,edge[top].to = b,edge[top].cap = w,edge[top].flow = 0,edge[top].cost = c,edge[top].next=head[a];
head[a] = top++;
edge[top].from = b,edge[top].to = a,edge[top].cap = 0,edge[top].flow = 0,edge[top].cost = -c,edge[top].next = head[b];
head[b] = top++;
}
int n,m;
typedef pair<int,int> P;
vector<P> man;
vector<P> home;
int S,T;
void getmap()
{
char ss[maxn];
man.clear();home.clear();
int a,b;
a = b = 0;
for(int i = 1 ; i <= n ; i++)
{
scanf("%s",ss);
for(int j = 0 ; ss[j]; j++)
{
if(ss[j] == 'H')
{
home.push_back({i,j+1});
a++;
}
else if(ss[j] == 'm')
{
man.push_back({i,j+1});
b++;
}
}
}
S = 0;T = a+b+1;
for(int i = 0 ; i < man.size() ;i++)
addege(S,i+1,1,0);
for(int j = 0 ; j < home.size() ; j++)
addege(a+j+1,T,1,0);
for(int i = 0 ; i < man.size() ; i++)
{
for(int j = 0 ; j < home.size() ; j++)
addege(i+1,a+j+1,1,abs(man[i].first-home[j].first)+abs(man[i].second-home[j].second));
}
}
bool vis[maxn];int dis[maxm];
int pre[maxn];
bool spfa(int s,int e)
{
queue<int> Q;
memset(vis,0,sizeof(vis));
memset(dis,0x3f,sizeof(dis));
memset(pre,-1,sizeof(pre));
dis[s] = 0;vis[s] = 1;Q.push(s);
while(!Q.empty())
{
int now = Q.front();
Q.pop();
vis[now] = 0;
for(int i = head[now];i!=-1;i = edge[i].next)
{
Edge e = edge[i];
if(e.cap>e.flow&&dis[e.to]>dis[now]+e.cost)
{
dis[e.to] = dis[now]+e.cost;
pre[e.to] = i;
if(!vis[e.to])
{
vis[e.to] = 1;
Q.push(e.to);
}
}
}
}
return pre[e]!=-1;
}
int MCMF(int s,int t,int &cost,int &flow)
{
flow = cost = 0;
while(spfa(s,t))
{
int Min = inf;
for(int i = pre[t];i!=-1;i = pre[edge[i^1].to])
{
Min = min(Min,edge[i].cap-edge[i].flow);
}
for(int i = pre[t];i!=-1;i = pre[edge[i^1].to])
{
edge[i].flow+=Min;
edge[i^1].flow -= Min;
cost+=edge[i].cost*Min;
}
flow+=Min;
}
}
int main()
{
while(scanf("%d%d",&n,&m)&&(n||m))
{
init();
getmap();
int flow,ans;
MCMF(S,T,ans,flow);
printf("%d\n",ans);
}
return 0;
}