标签:
题意:
给你一个N行M列的矩阵,其中“.”代表空地,“H”代表房子,“m”代表人,其中有n个房子和n个人。现在要求每个人进入一间房子,且人走一步需要支付1美元。
求最小需要花费多少美元才能让所有人都进入到房子中(每个人只能进入一间房子,每个房子只能容纳一个人)。
建图思路与安排工作那道题一样,设置一个超级源点(我习惯设置为0)和一个超级汇点,然后超级源点连接每个人(流量为1费用为0),
每个人连接每个房子(流量为1费用为人与房子的距离),然后每个房子连接超级汇点(流量为1费用为0)。
跑一遍spfa模版就出来了。
#include <iostream> #include <cstdio> #include <cstring> #include <string> #include <queue> #include <cmath> #include <vector> #include <algorithm> #include <limits.h> using namespace std; #define inf 1e8 #define maxn 205 #define maxm 100000 int head[maxn],eid; int dis[maxn]; bool vis[maxn]; int a[maxn]; int pre[maxn]; int cnt1,cnt2,cnt,result; int hx[maxn],hy[maxn],mx[maxn],my[maxn],cap[maxn][maxn]; struct node { int u,v,cap,next,cost; }eg[maxm]; int fun(int x,int y) { return fabs(mx[x]-hx[y])+fabs(my[x]-hy[y]); } void add(int u,int v,int cap,int cost) { eg[eid].u=u; eg[eid].v=v; eg[eid].cap=cap; eg[eid].next=head[u]; eg[eid].cost=cost; head[u]=eid++; eg[eid].u=v; eg[eid].v=u; eg[eid].cap=0; eg[eid].next=head[v]; eg[eid].cost=-cost; head[v]=eid++; } void makemap() { for(int i=1;i<=cnt2;i++) { add(0,i,1,0); for(int j=1;j<=cnt1;j++) { add(i,cnt2+j,1,fun(i,j)); } } for(int j=1;j<=cnt1;j++) add(cnt2+j,cnt,1,0); } bool spfa(int s,int t,int &flow,int &cost) { memset(vis,false,sizeof(vis)); for(int i=0;i<maxn;i++) dis[i]=inf; dis[s]=0; vis[s]=true; pre[s]=0; a[s]=inf; queue<int>q; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); vis[u]=false; for(int i=head[u];i!=-1;i=eg[i].next) { if(eg[i].cap&&dis[eg[i].v]>dis[u]+eg[i].cost) { dis[eg[i].v]=dis[u]+eg[i].cost; pre[eg[i].v]=i; a[eg[i].v]=min(a[u],eg[i].cap); if(!vis[eg[i].v]) { q.push(eg[i].v); vis[eg[i].v]=true; } } } } if(dis[t]==inf) return false; flow+=a[t]; cost+=dis[t]*a[t]; int u=t; while(u!=s) { eg[pre[u]].cap-=a[t]; eg[pre[u]^1].cap+=a[t]; u=eg[pre[u]].u; } return true; } int mincost(int s,int t) { int flow=0,cost=0; while(spfa(s,t,flow,cost)); return cost; } void init() { memset(head,-1,sizeof(head)); eid=0; } int main() { //freopen("in.txt","r",stdin); int n,m; char s[maxn]; while(~scanf("%d%d",&n,&m)&&n) { init(); cnt1=cnt2=0; for(int i=0;i<n;i++) { scanf("%s",s); for(int j=0;s[j]!=‘\0‘;j++) { if(s[j]==‘H‘) { cnt1++; hx[cnt1]=i; hy[cnt1]=j; } else if(s[j]==‘m‘) { cnt2++; mx[cnt2]=i; my[cnt2]=j; } } } cnt=cnt1+cnt2+1; makemap(); printf("%d\n",mincost(0,cnt)); } return 0; }
HDU1533 Going Home(最小费用最大流 spfa模版)
标签:
原文地址:http://www.cnblogs.com/d-e-v-i-l/p/4769223.html