P1251 餐巾计划问题 网络流
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn = 5005, inf = 0x3f3f3f3f; 5 struct Edge { 6 int from, to; 7 ll cap, flow, cost; 8 }; 9 10 struct MCMF { 11 int n, m, s, t; 12 vector<Edge> edges; 13 vector<int> G[maxn]; 14 int inq[maxn]; 15 ll d[maxn]; 16 int p[maxn]; 17 ll a[maxn]; 18 19 void init(int n) { 20 this->n = n; 21 for (int i = 1; i <= n; ++i) G[i].clear(); 22 edges.clear(); 23 } 24 25 void AddEdge(int from, int to, ll cap, ll cost) { 26 edges.push_back((Edge){from, to, cap, 0, cost}); 27 edges.push_back((Edge){to, from, 0, 0, -cost}); 28 m = edges.size(); 29 G[from].push_back(m-2); 30 G[to].push_back(m-1); 31 } 32 bool BellmanFord(int s, int t, ll& flow, ll& cost) { 33 for (int i = 1; i <= n; ++i) d[i] = inf; 34 memset(inq, 0, sizeof(inq)); 35 d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = inf; 36 37 queue<int> que; 38 que.push(s); 39 while (!que.empty()) { 40 int u = que.front(); que.pop(); 41 inq[u] = 0; 42 for (int i = 0; i < G[u].size(); ++i) { 43 Edge& e = edges[G[u][i]]; 44 if (e.cap > e.flow && d[e.to] > d[u] + e.cost) { 45 d[e.to] = d[u] + e.cost; 46 p[e.to] = G[u][i]; 47 a[e.to] = min(a[u], e.cap-e.flow); 48 if (!inq[e.to]) { que.push(e.to); inq[e.to] = 1; } 49 } 50 } 51 } 52 if (d[t] == inf) return false; 53 flow += a[t]; 54 cost += d[t] * a[t]; 55 int u = t; 56 while (u != s) { 57 edges[p[u]].flow += a[t]; 58 edges[p[u]^1].flow -= a[t]; 59 u = edges[p[u]].from; 60 } 61 return true; 62 } 63 ll mincost(int s, int t) { 64 ll flow = 0, cost = 0; 65 while (BellmanFord(s, t, flow, cost)); 66 return cost; 67 } 68 }mcmf; 69 int r[maxn]; 70 int main() { 71 int N; scanf("%d",&N); 72 for (int i = 1; i <= N; ++i) { 73 scanf("%d",&r[i]); 74 } 75 int p, m, f, n, s; 76 scanf("%d%d%d%d%d",&p,&m,&f,&n,&s); 77 78 /// i为干净餐巾量,i+N为脏餐巾量 79 int be = 2*N+1, ed = 2*N+2; 80 mcmf.init(2*N+2); 81 for (int i = 1; i <= N; ++i) { 82 /// 通过购买来获得干净餐巾 83 mcmf.AddEdge(be,i,r[i],p); 84 /// 当天的脏餐巾如何使用 85 mcmf.AddEdge(be,i+N,r[i],0); 86 /// 当天的脏餐巾留到明天 87 if (i+1 <= N) mcmf.AddEdge(i+N,(i+1)+N,inf,0); 88 /// 通过快洗部洗脏餐巾 89 if (i+m <= N) mcmf.AddEdge(i+N,i+m,inf,f); 90 /// 通过慢洗部洗脏餐巾 91 if (i+n <= N) mcmf.AddEdge(i+N,i+n,inf,s); 92 /// 使用当天的干净餐巾 93 mcmf.AddEdge(i,ed,r[i],0); 94 } 95 ll ans = mcmf.mincost(be,ed); 96 printf("%lld\n",ans); 97 return 0; 98 }