Going Home HDU-1533(费用流)

题意:

一个$N$行$M$列的矩阵,其中$"."$代表空地,$"H"$代表房子,$"m"$代表人,其中有$n$个房子和$n$个人。现在要求每个人进入其中的一间房子,且每人每走一步需要支付$1$美元。求最小需要花费多少美元能让所有人都进入到房子中(每个人只能进入一间房子,每个房子只能容纳一个人)。

思路:

费用流,人和源点建流量$1$费用$0$的边;人和房子建流量$1$,费用为哈夫曼距离的边;房子和汇点建流量$1$费用$0$的边。

代码:

  1 //#include<bits/stdc++.h>
  2 #include <set>
  3 #include <map>
  4 #include <stack>
  5 #include <cmath>
  6 #include <queue>
  7 #include <cstdio>
  8 #include <string>
  9 #include <vector>
 10 #include <cstring>
 11 #include <iostream>
 12 #include <algorithm>
 13 
 14 #define ll long long
 15 #define pll pair<ll,ll>
 16 #define pii pair<int,int>
 17 #define bug printf("*********
")
 18 #define FIN freopen("input.txt","r",stdin);
 19 #define FON freopen("output.txt","w+",stdout);
 20 #define IO ios::sync_with_stdio(false),cin.tie(0)
 21 #define ls root<<1
 22 #define rs root<<1|1
 23 #define Q(a) cout<<a<<endl
 24 
 25 using namespace std;
 26 const int inf = 0x3f3f3f3f;
 27 const ll Inf = 1e18 + 7;
 28 const int maxn = 1e4 + 5;
 29 const int mod = 1e9 + 7;
 30 
 31 ll gcd(ll a, ll b)
 32 {
 33     return b ? gcd(b, a % b) : a;
 34 }
 35 
 36 ll lcm(ll a, ll b)
 37 {
 38     return a / gcd(a, b) * b;
 39 }
 40 
 41 ll read()
 42 {
 43     ll p = 0, sum = 0;
 44     char ch;
 45     ch = getchar();
 46     while (1)
 47     {
 48         if (ch == '-' || (ch >= '0' && ch <= '9'))
 49             break;
 50         ch = getchar();
 51     }
 52 
 53     if (ch == '-')
 54     {
 55         p = 1;
 56         ch = getchar();
 57     }
 58     while (ch >= '0' && ch <= '9')
 59     {
 60         sum = sum * 10 + ch - '0';
 61         ch = getchar();
 62     }
 63     return p ? -sum : sum;
 64 }
 65 
 66 struct Dinic
 67 {
 68     int head[maxn], tot, cur[maxn];
 69     int dis[maxn];
 70     int s, e;
 71     queue<int>q;
 72 
 73     struct node
 74     {
 75         int v, w;
 76         int next;
 77     }p[maxn];
 78 
 79     void init()
 80     {
 81         tot = 0;
 82         memset(head, -1, sizeof head);
 83     }
 84 
 85     void add(int u, int v, int w)
 86     {
 87         p[tot].v = v;
 88         p[tot].w = w;
 89         p[tot].next = head[u];
 90         head[u] = tot++;
 91     }
 92 
 93     void addEdge(int u, int v, int w)
 94     {
 95         add(u, v, w);
 96         add(v, u, 0);
 97     }
 98 
 99     bool bfs()
100     {
101         memset(dis, 0, sizeof dis);
102         while (!q.empty())   q.pop();
103         dis[s] = 1;
104         q.push(s);
105         while (!q.empty())
106         {
107             int x = q.front();
108             q.pop();
109             for (int i = head[x]; i != -1; i = p[i].next)
110             {
111                 int v = p[i].v, w = p[i].w;
112                 if (!dis[v] && w)
113                 {
114                     dis[v] = dis[x] + 1;
115                     q.push(v);
116                 }
117             }
118         }
119         if (dis[e])  return true;
120         return false;
121     }
122 
123     int dfs(int x, int W)
124     {
125         if (x == e || W == 0)  return W;
126         int res = 0;
127         for (int i = cur[x]; i != -1; i = p[i].next)
128         {
129             cur[x] = p[i].next;
130             int v = p[i].v, w = p[i].w;
131             if (dis[v] == dis[x] + 1)
132             {
133                 int f = dfs(v, min(w, W));
134                 p[i].w -= f;
135                 p[i ^ 1].w += f;
136                 W -= f;
137                 res += f;
138                 if (W == 0)    break;
139             }
140         }
141         return res;
142     }
143 
144     int getMaxFlow()
145     {
146         int ans = 0;
147         while (bfs())
148         {
149             for (int i = s; i <= e; ++i) cur[i] = head[i];
150             ans += dfs(s, inf);
151         }
152         return ans;
153     }
154 }DC;
155 
156 struct stortest_Floyd {
157     int a[5000][5000];
158     void floyd(int num) {
159         for (int k = 1; k <= num; k++) {
160             for (int i = 1; i <= num; i++) {
161                 for (int j = 1; j <= num; j++) {
162                     if (a[i][j] > a[i][k] + a[k][j]) {
163                         a[i][j] = a[i][k] + a[k][j];
164                     }
165                 }
166             }
167         }
168     }
169 }Floyd;
170 
171 struct Min_Cost_Max_Flow
172 {
173     struct Edge
174     {
175         int from, to, cap, flow, cost;
176     };
177     
178     vector<Edge>edges;
179     vector<int>G[maxn];
180     bool vis[maxn];
181     int d[maxn], p[maxn], a[maxn];
182     int n, m, s, t;
183     
184     void init(int n, int s, int t)
185     {
186         this->n = n, this->s = s, this->t = t;
187         for (int i = 1; i <= n; ++i)
188         {
189             G[i].clear();
190         }
191         edges.clear();
192     }
193     
194     void add_edge(int from, int to, int cap, int cost)
195     {
196         edges.push_back({ from,to,cap,0,cost });
197         edges.push_back({ to,from,0,0,-cost });
198         m = edges.size();
199         G[from].push_back(m - 2);
200         G[to].push_back(m - 1);
201     }
202 
203     bool SPFA(int& flow, int& cost)
204     {
205         memset(d, inf, sizeof d);
206         memset(vis, false, sizeof vis);
207         memset(p, -1, sizeof p);
208         d[s] = 0, vis[s] = true, p[s] = 0, a[s] = inf;
209 
210         std::queue<int>que;
211         que.push(s);
212         while (!que.empty())
213         {
214             int u = que.front();
215             que.pop();
216             vis[u] = false;
217             for (int i = 0; i < G[u].size(); ++i)
218             {
219                 Edge& e = edges[G[u][i]];
220                 if (e.cap > e.flow&& d[e.to] > d[u] + e.cost)
221                 {
222                     d[e.to] = d[u] + e.cost;
223                     p[e.to] = G[u][i];
224                     a[e.to] = std::min(a[u], e.cap - e.flow);
225                     if (!vis[e.to])
226                     {
227                         vis[e.to] = true;
228                         que.push(e.to);
229                     }
230                 }
231             }
232         }
233 
234         if (d[t] == inf)   return false;
235         flow += a[t];
236         cost += d[t] * a[t];
237         int u = t;
238         while (u != s)
239         {
240             edges[p[u]].flow += a[t];
241             edges[p[u] ^ 1].flow -= a[t];
242             u = edges[p[u]].from;
243         }
244         return true;
245     }
246 
247     void solve(int& flow, int& cost)
248     {
249         flow = cost = 0;
250         while (SPFA(flow, cost));
251     }
252 };
253 
254 char s[maxn][maxn];
255 vector<pii>house, man;
256 
257 int main()
258 {
259     int n, m;
260     while (~scanf("%d %d", &n, &m))
261     {
262         if (n + m == 0)  break;
263         house.clear(), man.clear();
264         for (int i = 1; i <= n; ++i)
265         {
266             scanf("%s", s[i] + 1);
267             for (int j = 1; j <= m; ++j)
268             {
269                 if (s[i][j] == 'H')
270                     house.push_back({ i,j });
271                 else if (s[i][j] == 'm')
272                     man.push_back({ i,j });
273             }
274         }
275 
276         int sz1 = man.size(), sz2 = house.size();
277         int st = 0, ed = sz1 + sz2 + 1;
278         Min_Cost_Max_Flow mcmf;
279         mcmf.init(ed + 1, st, ed);
280         for (int i = 0; i < sz1; ++i)
281         {
282             mcmf.add_edge(st, i + 1, 1, 0);
283             int x1 = man[i].first, y1 = man[i].second;
284             for (int j = 0; j < sz2; ++j)
285             {
286                 int x2 = house[j].first, y2 = house[j].second;
287                 mcmf.add_edge(i + 1, sz1 + j + 1, 1, abs(x1 - x2) + abs(y1 - y2));
288             }
289         }
290         for (int i = 0; i < sz2; ++i)
291             mcmf.add_edge(i + sz1 + 1, ed, 1, 0);
292         int flow, cost;
293         mcmf.solve(flow, cost);
294         cout << cost << endl;
295     }
296 }

 

原文地址:https://www.cnblogs.com/zhang-Kelly/p/12593620.html