POJ 2195 Going Home【二分图最优匹配.KM】
题意: 给你一个图
HH. .m
. . . . .
. . . . .
. . . . .
mm. .H
m代表人 H 代表房子,一个人只能进一个房子,问你如何安排人进房,使得总步数最小。
分析: 可以用最小费用最大流,也可以用二分图最优匹配。
#include<stdio.h> #include<string.h> #define min(a,b)(a)<(b)?(a):(b) #define INF 0x1f1f1f #define maxn 105 #define clr(x)memset(x,0,sizeof(x)) int abs(int x){ return x>0?x:-x; } int sx[maxn],sy[maxn]; int lx[maxn],ly[maxn]; int link[maxn]; int map[maxn][maxn]; int n,m; int slack; int find(int x) { int i; sx[x]=1; for(i=1;i<=n;i++) if(!sy[i]) { int tmp=lx[x]+ly[i]-map[x][i]; if(tmp==0) { sy[i]=1; if(link[i]==0||find(link[i])) { link[i]=x; return 1; } } else if(tmp<slack) slack=tmp; } return 0; } int KM() { int i,j,v,dmin,sum; for(i=1;i<=n;i++) for(j=1;j<=n;j++) map[i][j]=-map[i][j]; for(i=1;i<=n;i++) { lx[i]=-INF; ly[i]=0; for(j=1;j<=n;j++) if(map[i][j]>lx[i]) lx[i]=map[i][j]; } for(v=1;v<=n;v++) { clr(sx); clr(sy); while(1) { slack=INF; if(find(v)) break; for(i=1;i<=n;i++) { if(sx[i]) { lx[i]-=slack; sx[i]=0; } if(sy[i]) { ly[i]+=slack; sy[i]=0; } } } } sum=0; for(i=1;i<=n;i++) sum-=map[link[i]][i]; return sum; } char a[maxn][maxn]; struct node { int x,y; }h[maxn],p[maxn]; int main() { int i,j,hn,pn; while(scanf("%d%d",&n,&m),n&&m) { hn=pn=1; for(i=0;i<n;i++) { scanf("%s",a[i]); for(j=0;j<m;j++) if(a[i][j]=='H'){ h[hn].x=i; h[hn++].y=j; } else if(a[i][j]=='m'){ p[pn].x=i; p[pn++].y=j; } } for(i=1;i<pn;i++) for(j=1;j<hn;j++) map[i][j]=abs(p[i].x-h[j].x)+abs(p[i].y-h[j].y); n=pn-1; memset(link,0,sizeof(link)); printf("%d\n",KM()); } return 0; }