文章標題 HDU 1533 : Going Home (最小費用最大流)

Going Home

題目鏈接
題意:在n*m的矩形上,有房子和人, 人到達房子的話費是曼哈頓距離,然後每個人走到一個房子,求最小的費用。
分析:最小費用最大流的模板
代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <math.h>
#include <vector>
using namespace std;
typedef long long ll;

const int inf=1000000;

const int mod=1e9+7;
const int maxn=100*100+10;
const int M=100000*2+10;

struct Edge{
    int to,nex,cap,flow,cost;
};

struct MFMC{
    Edge edge[M];
    int head[maxn],tot;
    int pre[maxn],dis[maxn];
    bool vis[maxn];
    int N;//節點的總個數,節點編號從0~N-1;
    void init(int n){
        N=n;
        tot=0;
        memset (head,-1,sizeof (head));
    }

    void addedge(int u,int v,int cap,int cost){
        edge[tot]=Edge{v,head[u],cap,0,cost};
        head[u]=tot++;
        edge[tot]=Edge{u,head[v],0,0,-cost};
        head[v]=tot++;
    }

    bool spfa(int s,int t){
        queue<int>q;
        for (int i=0;i<N;i++){
            dis[i]=inf;
            vis[i]=false;
            pre[i]=-1;
        }
        dis[s]=0;
        vis[s]=true;
        q.push(s);
        while (!q.empty()){
            int u=q.front();q.pop();
            vis[u]=false;
            for (int i=head[u];i!=-1;i=edge[i].nex){
                int v=edge[i].to;
                if (edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost){
                    dis[v]=dis[u]+edge[i].cost;
                    pre[v]=i;
                    if (!vis[v]){
                        vis[v]=true;
                        q.push(v);
                    }
                }
            }
        }
        if (pre[t]==-1)return false;
        else return true;
    }

    int minCostMaxflow(int s,int t,int &cost){
        int flow=0;
        cost=0;
        while (spfa(s,t)){
            int Min=inf;
            for (int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
                if ((Min>edge[i].cap-edge[i].flow)){
                    Min=edge[i].cap-edge[i].flow;
                }
            }
            for (int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
                edge[i].flow+=Min;
                edge[i^1].flow-=Min;
                cost+=edge[i].cost*Min;
            }
            flow+=Min;
        }
        return flow;
    }
}mfmc;

struct node {
    int x,y;
};
vector<node>house,man;
int n,m;
char mp[maxn][maxn];

int main()
{
    while (scanf ("%d%d",&n,&m)!=EOF){
        if (n==0&&m==0)break;
        mfmc.init(maxn);
        house.clear(),man.clear();
        for (int i=1;i<=n;i++){
            scanf ("%s",mp[i]+1);
            for (int j=1;j<=m;j++){
                if (mp[i][j]=='H')house.push_back(node{i,j});
                else if (mp[i][j]=='m')man.push_back(node{i,j}); 
            }
        }

        int s=man.size()*2+1,t=man.size()*2+2;
        for (int i=0;i<man.size();i++){
            mfmc.addedge(s,i,1,0);
            for (int j=0;j<house.size();j++){
                int dis=fabs(man[i].x-house[j].x)+fabs(man[i].y-house[j].y);
                mfmc.addedge(i,man.size()+j,1,dis);
            }
            mfmc.addedge(man.size()+i,t,1,0);
        }
        int cost=0;
        mfmc.minCostMaxflow(s,t,cost);
        printf ("%d\n",cost);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章