【KM】POJ2195/HDU1533-Going home
//最近没什么时间quq据说长得帅的人都在切八中,然而长得丑的人只能水水裸题
【题目大意】
给出一张地图及人和房屋的位置,求出每个人回到不同房屋所具有的最小代价和。
【思路】
最小权匹配,先O(n^2)求出每个人到任意房屋的距离后取反,就变成了裸的KM。数据范围很小,O(n^4)可以0ms过。
【错误点】
1.slack在每次循环中药重新设置为无穷大。2.内循环和外循环的循环变量重名了。3.变量名取太乱了用错了一次。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 const int INF=0x7fffffff; 8 const int MAXN=500; 9 int n,m; 10 int mx[MAXN],my[MAXN],hx[MAXN],hy[MAXN],numm,numh; 11 int g[MAXN][MAXN]; 12 int visx[MAXN],visy[MAXN],fx[MAXN],fy[MAXN],slack[MAXN],lk[MAXN]; 13 14 int Hungary_dfs(int u) 15 { 16 visx[u]=1; 17 for (int i=1;i<=numm;i++) 18 { 19 int wt=fx[u]+fy[i]-g[u][i]; 20 if (!visy[i] && wt==0) 21 { 22 visy[i]=1; 23 if (lk[i]==-1 || Hungary_dfs(lk[i])) 24 { 25 lk[i]=u; 26 return 1; 27 } 28 } 29 else if (wt<slack[i]) slack[i]=wt; 30 } 31 return 0; 32 } 33 34 int KM() 35 { 36 memset(lk,-1,sizeof(lk)); 37 for (int i=1;i<=numm;i++) 38 { 39 fx[i]=-INF; 40 fy[i]=0; 41 for (int j=1;j<=numm;j++) fx[i]=max(fx[i],g[i][j]); 42 } 43 44 for (int i=1;i<=numm;i++) 45 { 46 memset(visx,0,sizeof(visx)); 47 memset(visy,0,sizeof(visy)); 48 memset(slack,127,sizeof(slack));//slack每次都要初始化为无穷大 49 while (!Hungary_dfs(i)) 50 { 51 int delta=INF; 52 for (int j=1;j<=numm;j++) if (!visy[j]) delta=min(delta,slack[j]); 53 for (int j=1;j<=numm;j++)//这里忘掉了外面还套了一重循环,重复用了i! 54 { 55 if (visx[j]) 56 { 57 visx[j]=0; 58 fx[j]-=delta; 59 } 60 if (visy[j]) 61 { 62 visy[j]=0; 63 fy[j]+=delta; 64 } 65 } 66 } 67 } 68 69 int ret=0; 70 for (int i=1;i<=numm;i++) ret+=fx[i]+fy[i];//这里numm写成了n 71 return ret; 72 } 73 74 void init() 75 { 76 numm=numh=0; 77 for (int i=0;i<n;i++) 78 { 79 char c; 80 getchar(); 81 for (int j=0;j<m;j++) 82 { 83 scanf("%c",&c); 84 if (c=='m') 85 { 86 mx[++numm]=i; 87 my[numm]=j; 88 } 89 else if (c=='H') 90 { 91 hx[++numh]=i; 92 hy[numh]=j; 93 } 94 } 95 } 96 for (int i=1;i<=numm;i++) 97 for (int j=1;j<=numh;j++) 98 { 99 g[i][j]=-1*(abs(mx[i]-hx[j])+abs(my[i]-hy[j])); 100 } 101 } 102 103 int main() 104 { 105 while (scanf("%d%d",&n,&m)) 106 { 107 if (n==m && m==0) break; 108 init(); 109 cout<<KM()*(-1)<<endl; 110 } 111 return 0; 112 }