HDU 1533 二分图最小权匹配 Going Home

带权二分图匹配,把距离当做权值,因为是最小匹配,所以把距离的相反数当做权值求最大匹配。

最后再把答案取一下反即可。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <map>
  6 #include <vector>
  7 #include <cmath>
  8 #define MP make_pair
  9 using namespace std;
 10 
 11 typedef pair<int, int> PII;
 12 
 13 const int maxn = 100 + 10;
 14 
 15 int n;
 16 PII house[maxn], men[maxn];
 17 char grid[maxn][maxn];
 18 
 19 int row, col;
 20 
 21 int dist(const PII& a, const PII& b)
 22 { return abs(a.first - b.first) + abs(a.second - b.second); }
 23 
 24 //KM algorithm
 25 int W[maxn][maxn];
 26 int Lx[maxn], Ly[maxn];
 27 int lft[maxn];
 28 bool S[maxn], T[maxn];
 29 
 30 bool match(int u)
 31 {
 32     S[u] = true;
 33     for(int v = 1; v <= n; v++)
 34         if(Lx[u] + Ly[v] == W[u][v] && !T[v])
 35         {
 36             T[v] = true;
 37             if(!lft[v] || match(lft[v]))
 38             {
 39                 lft[v] = u;
 40                 return true;
 41             }
 42         }
 43     return false;
 44 }
 45 
 46 void update()
 47 {
 48     int a = 100000000;
 49     for(int u = 1; u <= n; u++) if(S[u])
 50         for(int v = 1; v <= n; v++) if(!T[v])
 51             a = min(a, Lx[u] + Ly[v] - W[u][v]);
 52     for(int u = 1; u <= n; u++)
 53     {
 54          if(S[u]) Lx[u] -= a;
 55          if(T[u]) Ly[u] += a;
 56     }
 57 }
 58 
 59 void KM()
 60 {
 61     for(int i = 1; i <= n; i++)
 62     {
 63         Lx[i] = *max_element(W[i]+1, W[i]+1+n);
 64         Ly[i] = 0;
 65         lft[i] = 0;
 66     }
 67     for(int u = 1; u <= n; u++)
 68     {
 69         for(;;)
 70         {
 71             memset(S, false, sizeof(S));
 72             memset(T, false, sizeof(T));
 73             if(match(u)) break;
 74             else update();
 75         }
 76     }
 77 }
 78 
 79 int main()
 80 {
 81     while(scanf("%d%d", &row, &col) == 2 && row)
 82     {
 83         n = 0;
 84 
 85         for(int i = 0; i < row; i++) scanf("%s", grid[i]);
 86         int hcnt = 0, mcnt = 0;
 87         for(int i = 0; i < row; i++)
 88             for(int j = 0; j < col; j++)
 89             {
 90                 if(grid[i][j] == 'H')
 91                     house[++hcnt] = MP(i, j);
 92                 else if(grid[i][j] == 'm')
 93                     men[++mcnt] = MP(i, j);
 94             }
 95 
 96         //build graph
 97         n = hcnt;
 98         for(int i = 1; i <= n; i++)
 99             for(int j = 1; j <= n; j++)
100                 W[i][j] = -dist(men[i], house[j]);
101 
102         KM();
103 
104         int ans = 0;
105         for(int i = 1; i <= n; i++) ans += W[lft[i]][i];
106         printf("%d
", -ans);
107     }
108 
109     return 0;
110 }
代码君
原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4782544.html