跟上题变化实在是太小了,直接套用模板即可!建图都几乎如出一辙。
#include <iostream>
#include <algorithm>
#include <queue>
#include <string.h>
using namespace std;
#define M 1005
#define inf 1 << 30
int n, m;
short capacity[M][M];
short flow[M][M];
short weight[M][M];
int shortestdistances[M];
int pre_node[M];
bool visited[M];
char s[105][105];
struct p {
int x, y;
} point[M];
/**
* insearch for shortest path from SuperSource[0], to SuperSink[n+m+1];
*
* @return whether there are shortest paths
*/
bool spfa() {
for (int i = 0; i <= n + m + 1; i++) {
shortestdistances[i] = inf;
pre_node[i] = -1;
visited[i] = false;
}
shortestdistances[0] = 0;
visited[0] = true;
queue <int> q;
q.push(0);
while (!q.empty()) {
int t = q.front();
q.pop();
visited[t] = false;
for (int i = 1; i <= n + m + 1; i++) {
if (capacity[t][i] > flow[t][i] && shortestdistances[i] > shortestdistances[t] + weight[t][i]) {
shortestdistances[i] = shortestdistances[t] + weight[t][i];
pre_node[i] = t;
if (!visited[i]) {
q.push(i);
visited[i] = true;
}
}
}
}
if (pre_node[n + m + 1] == -1) {
return false;
}
return true;
}
/**
* get maxflow
*/
void getMaxflow() { //if there is the shortest path, find the key edge that controls the flow, then change the flow
while (spfa()) {
int maxflow = inf;
int p = n + m + 1;
while (pre_node[p] != -1) { //find
maxflow = min(maxflow, capacity[pre_node[p]][p] - flow[pre_node[p]][p]); // from p'pre to p, the real flow equals to the capacity - flow_now
p = pre_node[p];
}
p = n + m + 1;
while (pre_node[p] != -1) { //change
flow[pre_node[p]][p] += maxflow;
flow[p][pre_node[p]] = -flow[pre_node[p]][p];
p = pre_node[p];
}
}
}
int main() {
int n1, m1;
while (cin>>n1>>m1&&(n1||m1)) {
int i, j;
n = 1;
m = 0;
for (i = 0; i < n1; i++) {
cin>>s[i];
for (j = 0; j < m1; j++) {
if (s[i][j] == 'm') {
point[n].x = i;
point[n].y = j;
n++;
}
}
}
for (i = 0; i < n1; i++) {
for (j = 0; j < m1; j++) {
if (s[i][j] == 'H') {
point[n + m].x = i;
point[n + m].y = j;
m++;
}
}
}
memset(capacity, 0, sizeof(capacity));
memset(flow, 0, sizeof(flow));
memset(weight, 0, sizeof(weight));
n--;
for (i = 1; i <= n; i++) {
for (j = 1; j <= m; j++) {
weight[i][n + j] = abs(point[i].x - point[n + j].x) + abs(point[i].y - point[n + j].y);
weight[n + j][i] = -weight[i][n + j];
}
}
for (i = 1; i <= n; i++) {
capacity[0][i] = 1;
}
for (i = n + 1; i <= n + m; i++) {
capacity[i][n + m + 1] = 1;
}
for (i = 1; i <= n; i++) {
for (j = 1; j <= m; j++) {
capacity[i][n + j] = 1;
}
}
getMaxflow();
int ans = 0, d;
for (j = 1; j <= n; j++) {
for (d = 1; d <= m; d++) {
ans += flow[j][d + n] * weight[j][d + n]; //计算总费用
}
}
cout << ans << endl;
}
return 0;
}