POJ-2195 Going Home (minimum cost maximum flow template)

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;
}
View Code

 

Guess you like

Origin www.cnblogs.com/kangkang-/p/11324602.html