终于切掉了我的第一道最小费用流了...
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#define MN 222
using namespace std;
struct Home{ int i,j; }H[MN];
struct Man{ int i,j; }M[MN];
struct Edge{ int u,v,c,f,next,cost; }E[MN*MN];
int head[MN],dis[MN],cur[MN],pre[MN];
int s,t,aug,min,EN,cntH,cntM,ans;
int mmin( int a,int b ){ return a<b?a:b; }
void addEdge( int u,int v,int c,int cc,int cost )
{
E[EN].v=v; E[EN].c=c; E[EN].f=0;
E[EN].cost=cost; E[EN].next=head[u]; head[u]=EN++;
E[EN].v=u; E[EN].c=cc; E[EN].f=0;
E[EN].cost=-cost; E[EN].next=head[v]; head[v]=EN++;
}
void spfa()
{
bool vis[MN];
queue<int>Q;
memset( vis,0,sizeof(vis) );
memset( dis,0x3f,sizeof(dis) );
Q.push(s);dis[s]=0;pre[s]=s;
while( !Q.empty() )
{
int cv=Q.front();Q.pop();
vis[cv]=false;
for( int i=head[cv];i!=-1;i=E[i].next )
{
if( dis[E[i].v]>dis[cv]+E[i].cost && E[i].f<E[i].c )
{
pre[E[i].v]=cv;
cur[E[i].v]=i;
dis[E[i].v]=dis[cv]+E[i].cost;
if( !vis[E[i].v] )
{
vis[E[i].v]=true;
Q.push(E[i].v);
}
}
}
}
}
int main()
{
char G[MN][MN];
int n,m;
while( scanf("%d %d",&n,&m)!=EOF )
{
if( n==0 && m==0 )
break;
cntH=cntM=0;ans=0;EN=0;
memset( head,-1,sizeof(head) );
for( int i=0;i<n;i++ )
scanf( "%s",&G[i] );
for( int i=0;i<n;i++ ) for( int j=0;j<m;j++ )
if( G[i][j]=='m' ){ M[cntM].i=i; M[cntM++].j=j; }
else if( G[i][j]=='H' ){ H[cntH].i=i; H[cntH++].j=j; }
s=0;t=cntH+cntM+1;
for( int i=0;i<cntH;i++ )
for( int j=0;j<cntM;j++ )
addEdge( i+1,cntH+j+1,1,0,abs(H[i].i-M[j].i)+abs(H[i].j-M[j].j) );
for( int i=0;i<cntH;i++ )
addEdge( s,i+1,1,0,0 );
for( int i=0;i<cntM;i++ )
addEdge( cntH+i+1,t,1,0,0 );
while( true ){
aug=0x3f3f3f3f;
spfa();
//printf( "%d\n",aug );
if( dis[t]==0x3f3f3f3f )
break;
for( int i=t;i!=s;i=pre[i] )
aug=mmin( aug,E[cur[i]].c-E[cur[i]].f );
for( int i=t;i!=s;i=pre[i] )
E[cur[i]].f+=aug,E[cur[i]^1].f-=aug;
ans+=aug*dis[t];
}
printf( "%d\n",ans );
}
return 0;
}