VOJ - Going Home (最小费用流)

Going Home

题目链接:Going Home POJ - 2195

题意

给你你一个n*m的图,里面’.’代表路,’H’房子,’m’人,人数和房子数是相等的所以现在需要所有的人到到达自己的房子里面,问最小需要多少时间,所有人都可以到达房子


思路

这道题本来是带权二分匹配的裸题,可惜我没有好的模板,于是用费用流硬刚,这也非常完美,就是只需用一个超级起点来连接所有的人,cap为1,同理用一个超级终点连接所有的房子,cap为1.注意模板需要确定总点数和初始化


代码

#include <iomanip>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cstdio>
#include <string>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <vector>
#include <sstream>
#include <memory>
#include <iostream>
#include <algorithm>
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define debug(x) cerr<<#x<<" = "<<(x)<<endl
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back

typedef double db;
typedef long long ll;
const int MAXN = (int)3e2+7;
const int INF = (int)0x3f3f3f3f;

struct edge{
    int to,cap,cost,rev;
    edge(int to = 0,int cap = 0,int cost = 0,int rev = 0):to(to),cap(cap),cost(cost),rev(rev){}
};

int N,M;
vector<edge> G[MAXN];
int dist[MAXN];
int prevv[MAXN];        //图的邻接表
int preve[MAXN];        //最短路的前驱节点和对应的边

void addedge(int from,int to,int cap,int cost) {
    G[from].pb(edge(to,cap,cost,(int)G[to].size()));
    G[to  ].pb(edge(from,0,-cost,(int)G[from].size()-1));
}

typedef pair<int,int> P;
priority_queue<P,vector<P>, greater<P> > qu;
int h[MAXN];

int min_cost_flow(int s,int t,int f){
    int res = 0;
    fill(h+1,h+1+N,0);
    while(f > 0){
        while (!qu.empty()) qu.pop();
        mmm(dist,0x3f);
        dist[s] = 0; qu.push(P(0,s));
        while(!qu.empty()){
            P now = qu.top(); qu.pop();
            if(dist[now.second] < now.first) continue;
            int v = now.second;
            rep(i,0,G[v].size()-1) {
                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;
                    qu.push(P(dist[e.to],e.to));
                }
            }
        }
        if(dist[t] == INF) return -1;
        rep(i,1,N) h[i] += dist[i];
        int d = f;
        for(int v = t; v != s; v = prevv[v])
            d = min(d,G[prevv[v]][preve[v]].cap);
        f -= 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;
}

struct Pos{
    int x,y;
    Pos(int x = 0,int y = 0):x(x),y(y){}
};
Pos Peo[MAXN],Hou[MAXN];
char pic[MAXN][MAXN];
int row,col;
int cnth,cntp;

void init(){
    rep(i,1,N) G[i].clear();
    cnth = cntp = 0;
}

int main()
{
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

    while (cin >> row >> col,row) {
        init();
        rep(i,1,row)
            cin >> pic[i]+1;

        rep(i,1,row) {
            rep(j,1,col) {
                if (pic[i][j] == 'H') Hou[++cnth] = Pos(i,j);
                if (pic[i][j] == 'm') Peo[++cntp] = Pos(i,j);
            }
        }

        rep(i,1,cntp) {
            rep(j,1,cnth) {
                int dis = abs(Peo[i].x-Hou[j].x)+abs(Peo[i].y-Hou[j].y);
                addedge(i,j+cntp,10,dis);
            }
        }
        int s = cntp+cnth+1,t = cntp+cnth+2;
        rep(i,1,cntp) addedge(s,i,1,0);
        rep(i,1,cnth) addedge(i+cntp,t,1,0);
        N = t;
        cout << min_cost_flow(s,t,cntp) << endl;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_40513946/article/details/81304202