Topic links: POJ-2195 Going Home
The meaning of problems
Given $ N $ $ M $ column line grid, 'm' represents a person, 'H' indicates a house, and the same number 'm' and 'H', a person can only enter a house, house You can only go to one person, who may embark both horizontally and vertically, and now want everyone to enter the house, and the shortest path.
Thinking
This is a bipartite graph with minimum weight matching problem can be solved directly with the minimum cost maximum flow.
Source to people of all even a capacity of 1, cost side 0 each person to each house is connected a capacity of 1, cost-edge distance of each house to sink even a capacity of 1, the cost is 0 side and ran to the minimum cost maximum flow.
Code
#include <iostream> #include <cstdio> #include <vector> #include <queue> #include <cstdlib> #include <cstring> #define N 5000 using namespace std; typedef pair<int, int> P; const int INF = 0x3f3f3f3f; struct Edge { int to, cap, cost, rev; Edge(int t, int c, int cc, int r) :to(t), cap(c), cost(cc), rev(r){} }; int V; vector<Edge> G[N]; int h[N]; int dist[N]; int prevv[N]; int preve[N]; void addedge(int from, int to, int cap, int 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 res = 0; fill(h, h + V, 0); while (true) { priority_queue<P, vector<P>, greater<P> >q; fill(dist, dist + V, INF); dist[s] = 0; q.push(P(0, s)); while (!q.empty()) { P p = q.top(); q.pop(); int v = p.second; if (dist[v] < p.first)continue; for (int i = 0; i < 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; q.push(P(dist[e.to], e.to)); } } } if (dist[t] == INF) break; for (int j = 0; j < V; j++) h[j] += dist[j]; int d = INF; for (int x = t; x != s; x = prevv[x]) d = min(d, G[prevv[x]][preve[x]].cap); if (d == 0) break; res += d * h[t]; for (int x = t; x != s; x = prevv[x]) { Edge &e = G[prevv[x]][preve[x]]; e.cap -= d; G[x][e.rev].cap += d; } } return res; } int main() { int n, m; while (~scanf("%d %d", &n, &m) && n && m) { vector<P> hou, man; char ch; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { scanf(" %c", &ch); if (ch == 'H') hou.push_back(make_pair(i, j)); else if (ch == 'm') man.push_back(make_pair(i, j)); } } int cnt = hou.size(); V = 2 * cnt + 2; int s = 2 * cnt, t = 2 * cnt + 1; for (int i = 0; i < V + 10; i++) G[i].clear(); for (int i = 0; i < cnt; i++) { for (int j = 0; j < cnt; j++) { addedge(i, cnt + j, 1, abs(man[i].first - hou[j].first) + abs(man[i].second - hou[j].second)); } } for (int i = 0; i < cnt; i++) { addedge(s, i, 1, 0); addedge(cnt + i, t, 1, 0); } printf("%d\n", min_cost_flow(s, t)); } return 0; }