[POJ2195]Going Home(带权最大匹配,KM,最小费用流)

题目链接:http://poj.org/problem?id=2195

题意:给个图,m代表人H代表房子。每一个m要有一个H,代价是曼哈顿距离。问让所有m找到房子的最小花费。

可以直接枚举m和H建二分图跑KM。

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <iomanip>
  4 #include <cstring>
  5 #include <climits>
  6 #include <complex>
  7 #include <cassert>
  8 #include <cstdio>
  9 #include <bitset>
 10 #include <vector>
 11 #include <deque>
 12 #include <queue>
 13 #include <stack>
 14 #include <ctime>
 15 #include <set>
 16 #include <map>
 17 #include <cmath>
 18 
 19 using namespace std;
 20 
 21 const int maxn = 310;
 22 const int inf = 0x3f3f3f3f;
 23 int nx,ny;
 24 int G[maxn][maxn];
 25 int linker[maxn],lx[maxn],ly[maxn];
 26 int slack[maxn];
 27 bool visx[maxn],visy[maxn];
 28 
 29 bool dfs(int x) {
 30     visx[x] = true;
 31     for(int y = 0; y < ny; y++) {
 32         if(visy[y])continue;
 33         int tmp = lx[x] + ly[y] - G[x][y];
 34         if(tmp == 0) {
 35             visy[y] = true;
 36             if(linker[y] == -1 || dfs(linker[y])) {
 37                 linker[y] = x;
 38                 return true;
 39             }
 40         }
 41         else if(slack[y] > tmp)
 42             slack[y] = tmp;
 43     }
 44     return false;
 45 }
 46 int km() {
 47     memset(linker,-1,sizeof(linker));
 48     memset(ly,0,sizeof(ly));
 49     for(int i = 0;i < nx;i++) {
 50         lx[i] = -inf;
 51         for(int j = 0;j < ny;j++)
 52             if(G[i][j] > lx[i])
 53                 lx[i] = G[i][j];
 54     }
 55     for(int x = 0;x < nx;x++) {
 56         for(int i = 0;i < ny;i++)
 57             slack[i] = inf;
 58         while(true) {
 59             memset(visx,false,sizeof(visx));
 60             memset(visy,false,sizeof(visy));
 61             if(dfs(x))break;
 62             int d = inf;
 63             for(int i = 0;i < ny;i++)
 64                 if(!visy[i] && d > slack[i])
 65                     d = slack[i];
 66             for(int i = 0;i < nx;i++)
 67                 if(visx[i])
 68                     lx[i] -= d;
 69             for(int i = 0;i < ny;i++) {
 70                 if(visy[i])ly[i] += d;
 71                 else slack[i] -= d;
 72             }
 73         }
 74     }
 75     int res = 0;
 76     for(int i = 0;i < ny;i++)
 77         if(linker[i] != -1)
 78             res += G[linker[i]][i];
 79     return res;
 80 }
 81 
 82 typedef pair<int,int> pii;
 83 char mp[maxn][maxn];
 84 int n, m;
 85 vector<pii> h, p;
 86 
 87 int main() {
 88   // freopen("in", "r", stdin);
 89     while(~scanf("%d%d",&n,&m) && n+m) {
 90         memset(mp, 0, sizeof(mp));
 91         h.clear(); p.clear();
 92         for(int i = 1; i <= n; i++) {
 93             scanf("%s", mp[i]+1);
 94         }
 95         for(int i = 1; i <= n; i++) {
 96             for(int j = 1; j <= m; j++) {
 97                 if(mp[i][j] == 'H') h.push_back(pii(i, j));
 98                 else if(mp[i][j] == 'm') p.push_back(pii(i, j));
 99             }
100         }
101         memset(G, 0, sizeof(G));
102         nx = h.size(); ny = p.size();
103         for(int i = 0; i < h.size(); i++) {
104             for(int j = 0; j < p.size(); j++) {
105                 int dis = abs(h[i].first - p[j].first) + abs(h[i].second - p[j].second);
106                 G[i][j] = -dis;
107             }
108         }
109         printf("%d
", -km());
110     }
111     return 0;
112 }
KM

也可以用最小费用流建模。

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <iomanip>
  4 #include <cstring>
  5 #include <climits>
  6 #include <complex>
  7 #include <cassert>
  8 #include <cstdio>
  9 #include <bitset>
 10 #include <vector>
 11 #include <deque>
 12 #include <queue>
 13 #include <stack>
 14 #include <ctime>
 15 #include <set>
 16 #include <map>
 17 #include <cmath>
 18 
 19 using namespace std;
 20 
 21 typedef long long LL;
 22 typedef struct Node {
 23     int u, v, next;
 24     LL c, w;
 25 }Node;
 26 const int maxn = 20010;
 27 const int maxm = 40010;
 28 const LL mod = 0x3f3f3f3fLL;
 29 const LL inf = (1LL<<55);
 30 int tot, head[maxn];
 31 LL dist[maxn];
 32 LL cost, flow;
 33 Node e[maxm];
 34 int pre[maxn];
 35 bool visit[maxn];
 36 queue<int> Q;
 37 int S, T, N;
 38 
 39 void init() {
 40     S = T = N = 0;
 41     memset(head, -1, sizeof(head));
 42     tot = 0;
 43 }
 44 
 45 void adde(int u, int v, LL c, LL w) {
 46     e[tot].u = u; e[tot].v = v; e[tot].c = c; e[tot].w = w; e[tot].next = head[u]; head[u] = tot++;
 47     e[tot].u = v; e[tot].v = u; e[tot].c = 0; e[tot].w = -w; e[tot].next = head[v]; head[v] = tot++;
 48 }
 49 bool spfa(int s, int t, int n) {
 50     int i;
 51     for(i = 0; i <= n; i++) {
 52         dist[i] = inf;
 53         visit[i] = 0;
 54         pre[i] = -1;
 55     }
 56     while(!Q.empty()) Q.pop();
 57     Q.push(s);
 58     visit[s] = true;
 59     dist[s] = 0;
 60     pre[s] = -1;
 61     while(!Q.empty()) {
 62         int u = Q.front();
 63         visit[u] = false;
 64         Q.pop();
 65         for(int j = head[u]; j != -1; j = e[j].next) {
 66             if(e[j].c > 0 && dist[u] + e[j].w < dist[e[j].v]) {
 67                 dist[e[j].v] = dist[u] + e[j].w;
 68                 pre[e[j].v] = j;
 69                 if(!visit[e[j].v]) {
 70                     Q.push(e[j].v);
 71                     visit[e[j].v] = true;
 72                 }
 73             }
 74         }
 75     }
 76     if(dist[t] == inf) return false;
 77     else return true;
 78 }
 79 LL ChangeFlow(int t) {
 80     LL det = mod;
 81     int u = t;
 82     while(~pre[u]) {
 83         u = pre[u];
 84         det = min(det, e[u].c);
 85         u = e[u].u;
 86     }
 87     u = t;
 88     while(~pre[u]) {
 89         u = pre[u];
 90         e[u].c -= det;
 91         e[u ^ 1].c += det;
 92         u = e[u].u;
 93     }
 94     return det;
 95 }
 96 LL MinCostFlow(int s, int t, int n) {
 97     LL mincost, maxflow;
 98     mincost = maxflow = 0;
 99     while(spfa(s, t, n)) {
100         LL det = ChangeFlow(t);
101         mincost += det * dist[t];
102         maxflow += det;
103     }
104     cost = mincost;
105     flow = maxflow;
106     return mincost;
107 }
108 
109 typedef pair<int,int> pii;
110 char mp[111][111];
111 int n, m;
112 vector<pii> h, p;
113 
114 int main() {
115   // freopen("in", "r", stdin);
116     while(~scanf("%d%d",&n,&m) && n+m) {
117         init();
118         memset(mp, 0, sizeof(mp));
119         h.clear(); p.clear();
120         for(int i = 1; i <= n; i++) {
121             scanf("%s", mp[i]+1);
122         }
123         for(int i = 1; i <= n; i++) {
124             for(int j = 1; j <= m; j++) {
125                 if(mp[i][j] == 'H') h.push_back(pii(i, j));
126                 else if(mp[i][j] == 'm') p.push_back(pii(i, j));
127             }
128         }
129         S = 0, T = h.size() + p.size() + 1, N = T + 1;
130         for(int i = 0; i < h.size(); i++) adde(S, i+1, 1, 0);
131         for(int i = 0; i < p.size(); i++) adde(h.size()+i+1, T, 1, 0);
132         for(int i = 0; i < h.size(); i++) {
133             for(int j = 0; j < p.size(); j++) {
134                 int dis = abs(h[i].first - p[j].first) + abs(h[i].second - p[j].second);
135                 int hi = i + 1;
136                 int pi = h.size() + j + 1;
137                 adde(hi, pi, 1, (LL)dis);
138             }
139         }
140         cout << MinCostFlow(S, T, N) << endl;
141     }
142     return 0;
143 }
原文地址:https://www.cnblogs.com/kirai/p/6769135.html