POJ2195 Going Home

给出一个 n∗ m 的字符串,其中 m 代表是人,H 代表的房子,代表立足地,每个人只能上/下/左/右移动。移动一步的花费是 1。问: 让所有人移动到房子(每个房子里面只能容纳一个人)里面的最小花费是多少?
 
最小费用最大流模板~
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=1014;
const int inf=1e9;
int cap[maxn][maxn];
int flow[maxn][maxn];
int cost[maxn][maxn];
int n;
int f;
int c;
int st,ed;
bool visit[maxn];
int pre[maxn];
int d[maxn];
bool spfa () {
    queue<int> q;
    fill (d,d+maxn,inf);
    fill (visit,visit+maxn,false);
    d[st]=0;
    visit[st]=true;
    q.push(st);
    while (!q.empty()) {
        int u=q.front();
        visit[u]=false;
        q.pop();
        for (int v=0;v<=n;v++) {
            if (cap[u][v]>flow[u][v]&&d[v]>d[u]+cost[u][v]) {
                d[v]=d[u]+cost[u][v];
                pre[v]=u;
                if (!visit[v]) {
                    visit[v]=true;
                    q.push(v);
                }
            }
        }
    }
    if (d[ed]>=inf) return false;
    return true;
}
void minCostMaxflow () {
    memset (flow,0,sizeof(flow));
    c=f=0;
    while (spfa()) {
        int Min=inf;
        for (int u=ed;u!=st;u=pre[u]) 
        Min=min(Min,cap[pre[u]][u]-flow[pre[u]][u]);
        for (int u=ed;u!=st;u=pre[u]) {
            flow[pre[u]][u]+=Min;
            flow[u][pre[u]]-=Min;
        }
        c+=d[ed]*Min;
        f+=Min;
    }
}
struct node {
    int x,y;
}Node1[maxn],Node2[maxn];
string s[maxn];
int main () {
    int N,M;
    while (scanf("%d %d",&N,&M)) {
        if (N==0&&M==0) break;
        int tol1=0,tol2=0;
        for (int i=0;i<N;i++) {
            cin>>s[i];
            for (int j=0;j<M;j++) {
                if (s[i][j]=='m') {
                    tol1++;
                    Node1[tol1].x=i;
                    Node1[tol1].y=j;
                }
                else if (s[i][j]=='H') {
                    tol2++;
                    Node2[tol2].x=i;
                    Node2[tol2].y=j;
                }
            }
        }
        st=0;
        n=tol1+tol2+1;
        ed=tol1+tol2+1;
        memset(cap,0,sizeof(cap));
        memset(cost,0,sizeof(cost));
        for (int i=1;i<=tol1;i++) {
            cost[0][i]=cost[i][0]=0;
            cap[0][i]=1;
        } 
        for (int i=1;i<=tol2;i++) {
            cost[tol1+i][ed]=0;
            cap[tol1+i][ed]=1;
        }
        for (int i=1;i<=tol1;i++)
        for (int j=1;j<=tol2;j++) {
            cost[i][tol1+j]=abs(Node1[i].x-Node2[j].x)+abs(Node1[i].y-Node2[j].y);
            cost[tol1+j][i]=-cost[i][tol1+j];
            cap[i][tol1+j]=1;
        }
        minCostMaxflow();
        printf ("%d\n",c);
    }
    return 0;
}

 

posted @ 2020-02-16 12:47  zlc0405  阅读(139)  评论(0编辑  收藏  举报