最小费用最大流,直接贴模板过,注意数组开小了会RE
/*最小费用最大流*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
using namespace std;
struct node
{
int u,v,cost,flow,next;
};
struct Pos
{
int row;
int col;
}man[205],house[205];
int n,m;
const int INF=1000000;
node edges[2000005];
int head[505],e;
int pre[505],in[505],cost[505],flow[505];
int s,t;
queue<int> Q;
void add(int u,int v,int flow,int cost)
{
edges[e].u=u;
edges[e].v=v;
edges[e].cost=cost;
edges[e].flow=flow;
edges[e].next=head[u];
head[u]=e++;
}
void Add(int u,int v,int flow,int cost)
{
add(u,v,flow,cost);
add(v,u,0,-cost);
}
int SPFA(int s,int t)
{
int i,u,v;
memset(pre,-1,sizeof(pre));
memset(flow,0,sizeof(flow));
memset(in,0,sizeof(in));
for(i=0;i<=t;i++) cost[i]=INF;
while(!Q.empty()) Q.pop();
Q.push(s);
in[s]=1;
flow[s]=INF;
cost[s]=0;
while(!Q.empty())
{
u=Q.front();
Q.pop();
in[u]=0;
for(i=head[u];i!=-1;i=edges[i].next)
{
v=edges[i].v;
if(edges[i].flow>0&&cost[v]>cost[u]+edges[i].cost)
{
cost[v]=cost[u]+edges[i].cost;
pre[v]=i;
flow[v]=min(flow[u],edges[i].flow);
if(!in[v])
{
in[v]=1;
Q.push(v);
}
}
}
}
return flow[t];
}
int MCMF(int s,int t)
{
int mincost=0,minflow,i;
while(minflow=SPFA(s,t))
{
for(i=pre[t];i!=-1;i=pre[edges[i].u])
{
mincost+=minflow*edges[i].cost;
edges[i].flow-=minflow;
edges[i^1].flow+=minflow;
}
}
return mincost;
}
int main()
{
int mc,nc;
while(scanf("%d %d",&n,&m)&&n!=0&&m!=0)
{
memset(head,-1,sizeof(head));
char s[105];
mc = nc = 1;
for(int i = 0;i<n;i++)
{
scanf("%s",s);
for(int j = 0;j<m;j++)
{
if(s[j]=='m')
{
man[mc].row = i;
man[mc++].col = j;
}
if(s[j]=='H')
{
house[nc].row = i;
house[nc++].col = j;
}
}
}
for(int i = 1;i<mc;i++)
for(int j = 1;j<nc;j++)
{
int len = abs((double)(house[j].row-man[i].row))+abs((double)(house[j].col-man[i].col));
Add(i,mc+j-1,1,len);
}
for(int i = 1;i<mc;i++)
Add(0,i,1,0);
for(int j = 1;j<nc;j++)
Add(mc-1+j,mc+nc-1,1,0);
int ans = MCMF(0,mc+nc-1);
printf("%d\n",ans);
}
return 0;
}