传送门:http://poj.org/problem?id=2195
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 26151 | Accepted: 13117 |
Description
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 28
给一个长为 H 宽为 W 的地图,地图上 m 代表人, H 代表家,求所有人回到家的最小权值之和。(人到家的距离为 哈密顿距离)
拆点建二分图,距离反转,KM算法求二分图的最大权值匹配,那么去掉负号最大的就是最小的权值之和了。
AC code:
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #define INF 0x3f3f3f3f 6 using namespace std; 7 const int MAXN = 110; 8 9 char str[MAXN][MAXN]; 10 int c[MAXN][MAXN]; 11 int ex[MAXN], ey[MAXN]; 12 bool visx[MAXN], visy[MAXN]; 13 int match[MAXN]; 14 int HH, WW; 15 int numx, numy; 16 17 struct date 18 { 19 int x, y; 20 }M[MAXN], H[MAXN]; 21 22 bool dfs(int x) 23 { 24 visx[x] = true; 25 26 for(int y = 0; y < numx; y++){ 27 if(!visy[y] && ex[x]+ey[y]-c[x][y] == 0){ 28 visy[y] = true; 29 30 if(match[y] == -1 || dfs(match[y])){ 31 match[y] = x; 32 return true; 33 } 34 } 35 } 36 return false; 37 } 38 39 void KM() 40 { 41 memset(ey, 0, sizeof(ey)); 42 memset(match, -1, sizeof(match)); 43 44 for(int i = 0; i < numx; i++){ 45 ex[i] = c[i][0]; 46 for(int j = 1; j < numx; j++){ 47 if(c[i][j] > ex[i]) 48 ex[i] = c[i][j]; 49 } 50 } 51 52 for(int i = 0; i < numx; i++){ 53 while(1){ 54 memset(visx, 0, sizeof(visx)); 55 memset(visy, 0, sizeof(visy)); 56 57 if(dfs(i)) break; 58 59 int d = INF; 60 for(int j = 0; j < numx; j++){ 61 if(visx[j]){ 62 for(int k = 0; k < numx; k++){ 63 if(!visy[k] && ex[j]+ey[k]-c[j][k] < d) 64 d = ex[j] + ey[k] - c[j][k]; 65 } 66 } 67 } 68 69 for(int j = 0; j < numx; j++){ 70 if(visx[j]) ex[j]-=d; 71 if(visy[j]) ey[j]+=d; 72 } 73 } 74 } 75 76 int res = 0; 77 for(int i = 0; i <numx; i++){ 78 res+=c[match[i]][i]; 79 } 80 printf("%d\n", -res); 81 } 82 83 int main() 84 { 85 while(~scanf("%d %d", &HH, &WW) && (HH+WW)){ 86 numx = numy = 0; 87 for(int i = 0; i < HH; i++){ 88 scanf("%s", &str[i]); 89 90 for(int j = 0; j < WW; j++){ 91 if(str[i][j] == ‘m‘){ 92 M[numx].x = i; 93 M[numx++].y = j; 94 } 95 else if(str[i][j] == ‘H‘){ 96 H[numy].x = i; 97 H[numy++].y = j; 98 } 99 } 100 } 101 102 for(int i = 0; i < numx; i++){ 103 for(int j = 0; j < numx; j++) 104 c[i][j] = -(abs(M[i].x - H[j].x) + abs(M[i].y - H[j].y)); 105 } 106 KM(); 107 } 108 return 0; 109 }
POJ 2195 Going Home 【二分图最小权值匹配】
原文:https://www.cnblogs.com/ymzjj/p/10004591.html