链接:http://poj.org/problem?id=2195
这道题是二分图的最佳匹配问题,而且属于最小匹配,km算法的模版题,题目保证了人数和房子数相等,这是自己第一道km算法题,刚开始对km算法不理解,看各种讲解,终于搞懂了其运行过程和能求出解的原因。km算法保证在整个算法的运行过程中对于匹配x,y保证lx[x]+ly[y]>=w(x,y);最终找到的是lx[x]+ly[y]=w(x,y)的解。
View Code
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #define N 200 5 #define inf 0x7fffffff 6 using namespace std; 7 struct point 8 { 9 int x,y; 10 }; 11 point ph[N],pm[N]; 12 int lx[N],ly[N]; 13 int map[N][N]; 14 int match[N]; 15 int usedx[N],usedy[N],flag; 16 char g[N][N]; 17 int abs(int a) 18 { 19 return a>=0?a:-a; 20 } 21 int max(int a,int b) 22 { 23 return a>b?a:b; 24 } 25 int min(int a,int b) 26 { 27 return a<b?a:b; 28 } 29 int h,m; 30 void build() 31 { 32 int i,j; 33 for(i=1;i<=h;i++) 34 for(j=1;j<=m;j++) 35 map[i][j]=abs(ph[i].x-pm[j].x)+abs(ph[i].y-pm[j].y); 36 } 37 bool dfs(int x) 38 { 39 int i,j,k; 40 usedx[x]=flag; 41 for(i=1;i<=m;i++) 42 { 43 if(usedy[i]!=flag&&lx[x]+ly[i]==map[x][i]) 44 { 45 usedy[i]=flag; 46 if(match[i]==-1||dfs(match[i])) 47 { 48 match[i]=x; 49 return true; 50 } 51 } 52 } 53 return false; 54 } 55 int km() 56 { 57 memset(lx,127,sizeof(lx)); 58 memset(ly,0,sizeof(ly)); 59 build(); 60 flag=0; 61 int res=0; 62 int i,j,k,d; 63 for(i=1;i<=h;i++) 64 for(j=1;j<=m;j++) 65 lx[i]=min(lx[i],map[i][j]);//最大权匹配就取最大值,最小权匹配就取最小值 66 memset(match,-1,sizeof(match)); 67 for(i=1;i<=h;i++) 68 { 69 flag++; 70 while(!dfs(i)) 71 { 72 d=inf; 73 for(j=1;j<=h;j++) 74 { 75 if(usedx[j]==flag) 76 for(k=1;k<=m;k++) 77 if(usedy[k]!=flag) 78 d=min(map[j][k]-lx[j]-ly[k],d); 79 } 80 for(j=1;j<=h;j++) 81 if(usedx[j]==flag) 82 lx[j]+=d; 83 for(j=1;j<=m;j++) 84 { 85 if(usedy[j]==flag) 86 ly[j]-=d; 87 } 88 flag++; 89 } 90 } 91 for(i=1;i<=m;i++) 92 res+=map[match[i]][i]; 93 return res; 94 } 95 int main() 96 { 97 int r,c,i,j,k; 98 char s; 99 while(scanf("%d%d",&r,&c)&&(r||c)) 100 { 101 h=m=0; 102 for(i=1;i<=r;i++) 103 scanf("%s",g[i]+1); 104 for(i=1;i<=r;i++)//建图过程 105 for(j=1;j<=c;j++) 106 { 107 if(g[i][j]=='H') 108 { 109 ph[++h].x=i; 110 ph[h].y=j; 111 } 112 if(g[i][j]=='m') 113 { 114 pm[++m].x=i; 115 pm[m].y=j; 116 } 117 } 118 //printf("%d %d\n",h,m); 119 printf("%d\n",km()); 120 } 121 return 0; 122 }