• 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 }
    代码君
  • 相关阅读:
    MySQl查询语句大全
    并发编程三
    并发编程二
    并发编程
    网络编程
    面向对象高级进阶
    python中的面向对象和面向过程
    为什么还需要学习TypeScript
    Chrome 神器,神奇的技巧
    vue-property-decorator知识梳理
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4782544.html
Copyright © 2020-2023  润新知