KM算法求的是二分图最优匹配,权值最大。当让求权值最小时,只需把原来的权值都改成负值即可,,其他的都不用变。。。。。。。。。题目:
Time Limit:1000MS | Memory Limit:65536K | |
Total Submissions:12101 | Accepted:6261 |
Description
Your task is to compute the minimum amount of money you need to pay in order to send these n little men into those n different houses. The input is a map of the scenario, a '.' means an empty space, an 'H' represents a house on that point, and am 'm' indicates there is a little man on that point.

You can think of each point on the grid map as a quite large square, so it can hold n little men at the same time; also, it is okay if a little man steps on a grid with a house without entering that house.
Input
Output
Sample Input
2 2 .m H. 5 5 HH..m ..... ..... ..... mm..H 7 8 ...H.... ...H.... ...H.... mmmHmmmm ...H.... ...H.... ...H.... 0 0
Sample Output
2 10 28ac代码:
#include <iostream>
#include <string.h>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
int n,m;
const int mn=105;
int sx[mn],sy[mn],vx[mn],vy[mn],matchx[mn];
char map[mn][mn];
int length[mn][mn];
int countt,num;
int slack[mn];
struct house{
int x,y;
}hh[mn];
struct men{
int x,y;
}mm[mn];
void chushihua(){
countt=0;
num=0;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
cin>>map[i][j];
if(map[i][j]=='H'){
hh[countt].x=i;
hh[countt].y=j;
countt++;
}
if(map[i][j]=='m'){
mm[num].x=i;
mm[num].y=j;
num++;
}
}
}
for(int i=0;i<countt;++i){
sy[i]=0;sx[i]=INT_MIN;
for(int j=0;j<num;++j){
length[i][j]=0-((abs(hh[i].x-mm[j].x))+(abs(hh[i].y-mm[j].y)));
//printf("%d\n",length[i][j]);
if(length[i][j]>sx[i])
sx[i]=length[i][j];
}
}
}
bool dfs(int x){
vx[x]=1;
for(int i=0;i<num;++i){
int xx=sx[x]+sy[i]-length[x][i];
if(!vy[i]&&xx==0){
vy[i]=1;
if(matchx[i]==-1||dfs(matchx[i])){
matchx[i]=x;
//printf("x=%d i=%d\n",x,i);
return true;
}
}
else if(slack[i]>xx)
slack[i]=xx;
}
return false;
}
void bestmatch(){
for(int i=0;i<countt;++i){
while(1){
memset(vx,0,sizeof(vx));
memset(vy,0,sizeof(vy));
for(int j=0;j<countt;++j)
slack[j]=INT_MAX;
if(dfs(i))
break;
int dd=INT_MAX;
for(int j=0;j<countt;++j){
if(!vy[j]&&slack[j]<dd)
dd=slack[j];
}
for(int j=0;j<countt;++j)
{
if(vx[j])
sx[j]-=dd;
if(vy[j])
sy[j]+=dd;
}
}
}
}
int main(){
while(scanf("%d%d",&n,&m)&&n&&m){
memset(sx,0,sizeof(sx));
memset(sy,0,sizeof(sy));
memset(matchx,-1,sizeof(matchx));
memset(length,0,sizeof(length));
memset(map,'0',sizeof(map));
memset(slack,0,sizeof(slack));
chushihua();
bestmatch();
int sum=0;
for(int i=0;i<countt;++i)
{/*printf("%d ",length[matchx[i]][i]);*/sum+=(0-length[matchx[i]][i]);}
printf("%d\n",sum);
}
return 0;
}