题目链接:http://poj.org/problem?id=2195
#include <iostream>
#include <vector>
#include <queue>
#include <functional>
#include <cstring>
#include <cstdio>
using namespace std;
#define INF 0x3f3f3f3f
#define MAX_V 100*100*2+10
typedef pair<int, int> P;
struct edge
{
int to;
int cap;
int cost;
int rev;
edge(int to, int cap, int cost, int rev) :to(to), cap(cap), cost(cost), rev(rev){}
};
int V;
vector<edge> G[MAX_V];
int h[MAX_V];
int dist[MAX_V];
int prevv[MAX_V];
int preve[MAX_V];
//
void add_edge(int from, int to, int cap, int cost)
{
//printf("%d %d %d %d\n",from,to,cap,cost);
G[from].push_back(edge(to, cap, cost, G[to].size()));
G[to].push_back(edge(from, 0, -cost, G[from].size() - 1));
}
int min_cost_flow(int s, int t, int f)
{
int res = 0;
memset(h, 0, sizeof(h));
while (f > 0)
{
priority_queue<P, vector<P>, greater<P> > que;
memset(dist, INF, sizeof(dist));
dist[s] = 0;
que.push(P(0, s));
while (!que.empty())
{
P p = que.top(); que.pop();
int v = p.second;
if (dist[v] < p.first) continue;
for (int i = 0; i <(int) G[v].size(); ++i)
{
edge &e = G[v][i];
if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to])
{
dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
prevv[e.to] = v;
preve[e.to] = i;
que.push(P(dist[e.to], e.to));
}
}
}
if (dist[t] == INF)
{
return -1;
}
for (int v = 0; v < V; ++v)
{
h[v] += dist[v];
}
int d = f;
for (int v = t; v != s; v = prevv[v])
{
d = min(d, G[prevv[v]][preve[v]].cap);
}
f -= d;
//printf("d = %d\n",d);
res += d * h[t];
for (int v = t; v != s; v = prevv[v])
{
edge &e = G[prevv[v]][preve[v]];
e.cap -= d;
G[v][e.rev].cap += d;
}
}
return res;
}
void Clear()
{
memset(dist,0,sizeof(dist));
memset(prevv,0,sizeof(prevv));
memset(preve,0,sizeof(preve));
for (int i = 0; i < V; ++i)
{
G[i].clear();
}
}
int N, M;
inline int id_of(const int& y, const int& x)
{
return y*M+x;
}
vector<pair<int,int> > H,m;
int main(int argc, char *argv[])
{
while(scanf("%d%d", &N, &M)==2)
{
if(N==0&&M==0)
break;
H.clear(),m.clear();
V = N*M+2;Clear();
int s = V-2,t = V-1;
int ans =0;
for (int y = 0; y < N; ++y)
{
for (int x = 0; x < M; ++x)
{
char ch;
scanf(" %c", &ch);
int current = id_of(y, x);
if(ch == 'H')
{
add_edge(s,current,1,0);
ans ++;
H.push_back(make_pair(x,y));
}
else if(ch == 'm')
{
add_edge(current,t,1,0);
m.push_back(make_pair(x,y));
}
}
}
for(int i=0;i<ans;i++)
{
for(int j=0;j<ans;j++)
{
int tmp = abs(H[i].first - m[j].first) + abs(H[i].second-m[j].second);
//printf("tmp = %d\n",tmp);
int from = id_of(H[i].second,H[i].first),to = id_of(m[j].second,m[j].first);
add_edge(from,to,INF,tmp);
}
}
printf("%d\n", min_cost_flow(s,t,ans));
}
return 0;
}