POJ-2195 Going Home(最小费用最大流模板)

Posted kangkang-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ-2195 Going Home(最小费用最大流模板)相关的知识,希望对你有一定的参考价值。

题目链接:POJ-2195 Going Home

题意

给出$N$行$M$列的网格,‘m‘表示人,‘H‘表示房子,且‘m‘和‘H‘的数量相同,一个人只能进一间房子,一间房子也只能给一个人进去,人可走上下左右四个方向,现在要让所有人进入房子,求最短路径和。


思路

这是一个二分图带权最小匹配问题,可直接用最小费用最大流求解。

源点向人各连一条容量为1,费用为0的边,每个人向每间房子连容量为1,费用为距离的边,每间房子向汇点连容量为1,费用为0的边,然后跑最小费用最大流即可。


代码实现

技术图片
#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

 

以上是关于POJ-2195 Going Home(最小费用最大流模板)的主要内容,如果未能解决你的问题,请参考以下文章

POj 2195 Going Home(费用流)

Going Home POJ - 2195 (最小费用最大流)

POJ 2195:Going Home(最小费用最大流)

POJ 2195 - Going Home - [最小费用最大流][MCMF模板]

POJ 2195 Going Home 最小费用最大流 尼玛,心累

[poj] 2195 Going Home || 最小费用最大流