POJ 2195 Going Home【最小费用最大流】
题意: 给你一个图
HH. .m
. . . . .
. . . . .
. . . . .
mm. .H
m代表人 H 代表房子,一个人只能进一个房子,问你如何安排人进房,使得总步数最小。
分析: 可以用最小费用最大流,也可以用二分图最有匹配。
最小费用最大流
#include<stdio.h> #include<string.h> #define min(a,b)(a)<(b)?(a):(b) #define inf 0x1f1f1f int ab(int x){ return x>0? x:-x;} int cap[500][500]; int cost[500][500]; int q[10000]; int pre[500]; int dis[500]; int v[500]; char g[500][500]; int s,t; int n,m; int tot=0; struct node { int x,y; }h[500],p[500]; int spfa() { int i,x,front,rear; front=rear=0; for(i=0;i<=t;i++) dis[i]=inf; memset(v,0,sizeof(v)); q[rear++]=s; dis[s]=0; v[s]=1; while(front<rear) { x=q[front++]; v[x]=0; for(i=0;i<=t;i++) { if(cap[x][i]&&dis[i]>dis[x]+cost[x][i]) { dis[i]=dis[x]+cost[x][i]; pre[i]=x; if(!v[i]) { v[i]=1; if(dis[i]<=dis[x]&&front>0) q[--front]=i; else q[rear++]=i; } } } } if(dis[t]!=inf) return 1; return 0; } int costflow() { int tot=0; int flow=0; int u; int minf=inf; while(spfa()) { for(u=t;u!=s;u=pre[u]) minf=min(minf,cap[pre[u]][u]); for(u=t;u!=s;u=pre[u]) { cap[pre[u]][u]-=minf; cap[u][pre[u]]+=minf; flow+=cost[pre[u]][u]*minf; } } return flow; } int main() { int i,j,pn,hn; while(scanf("%d%d",&n,&m),n||m) { memset(cap,0,sizeof(cap)); memset(cost,0,sizeof(cost)); hn=1;pn=1; for(i=1;i<=n;i++) { scanf("%s",g[i]); for(j=0;j<m;j++) if(g[i][j]=='m'){ p[pn].x=i; p[pn++].y=j; } else if(g[i][j]=='H'){ h[hn].x=i; h[hn++].y=j; } } s=0; hn--; pn--; t=pn*2+1; for(i=1;i<=pn;i++) { cap[s][i]=1; cost[s][i]=0; } for(i=pn+1;i<t;i++) { cap[i][t]=1; cost[i][t]=0; } for(i=1;i<=pn;i++) for(j=1;j<=hn;j++) { cap[i][j+pn]=1; cost[i][j+pn]=ab(p[i].x-h[j].x)+ab(p[i].y-h[j].y); cost[j+pn][i]-=cost[i][j+pn]; } printf("%d\n",costflow()); } return 0; }



浙公网安备 33010602011771号