1. 程式人生 > >loj 6008 餐巾計劃 - 費用流

loj 6008 餐巾計劃 - 費用流

不清楚 using rap node const ron printf 這一 als

題目傳送門

  傳送門

題目大意

  (經典題還不知道題意?)

  容易想到需要把未使用的餐巾和已經使用的餐巾分開。

  設$X_i$表示第$i$天已經的使用餐巾的點,設$Y_i$表示第$i$天還未使用的餐巾的點

  我們知道使用過的餐巾數量 = 洗出來的餐巾數量 + 購買的餐巾數量(一個餐巾被多次洗出來算多次)。

  右邊是啥,我們不清楚,但是我們清楚每一天新增的使用過的餐巾的數量,所以源點向$X_i$連一條容量為$r_i$,費用為0的邊。

  接下來還有幾種連邊:

  • $X_i$向$X_{i + 1}$連一條容量為$\infty$,費用為0的邊(使用過的餐巾還是使用過的,$i < n$)。
  • $Y_i$向$Y_{i + 1}$連一條容量為$\infty$,費用為0的邊
  • $X_i$向$Y_{i + M}$連一條容量為$\infty$,費用為$F$的邊
  • $X_i$向$Y_{i + N}$連一條容量為$\infty$,費用為$S$的邊

  對於第$i$天會用掉$r_i$的餐巾,所以$Y_i$向匯點連一條容量為$r_i$,費用為0的邊。

  還有一個購買餐巾,它直接會變成這一天的未使用過的餐巾,所以原點向$Y_i$連一條容量為$\infty$,費用為$p$的邊。

Code

  1 /**
  2  * loj
  3  * Problem#6008
  4  * Accepted
5 * Time: 701ms 6 * Memory: 636k 7 */ 8 #include <iostream> 9 #include <cstdlib> 10 #include <cstdio> 11 #include <queue> 12 using namespace std; 13 typedef bool boolean; 14 15 template <typename T> 16 void pfill(T* pst, const T* ped, T val) {
17 for ( ; pst != ped; *(pst++) = val); 18 } 19 20 typedef class Edge { 21 public: 22 int ed, nx, r, c; 23 24 Edge(int ed = 0, int nx = 0, int r = 0, int c = 0) : ed(ed), nx(nx), r(r), c(c) { } 25 } Edge; 26 27 typedef class MapManager { 28 public: 29 int* h; 30 vector<Edge> es; 31 32 MapManager() { } 33 MapManager(int n) { 34 h = new int[(n + 1)]; 35 pfill(h, h + n + 1, -1); 36 } 37 38 void addEdge(int u, int v, int r, int c) { 39 es.push_back(Edge(v, h[u], r, c)); 40 h[u] = (signed) es.size() - 1; 41 } 42 43 void addArc(int u, int v, int cap, int c) { 44 addEdge(u, v, cap, c); 45 addEdge(v, u, 0, -c); 46 } 47 48 Edge& operator [] (int p) { 49 return es[p]; 50 } 51 } MapManager; 52 53 const signed int inf = (signed) (~0u >> 1); 54 55 class Graph { 56 public: 57 int S, T; 58 MapManager g; 59 60 int *le; 61 int *f, *mf; 62 boolean *vis; 63 64 // be sure T is the last node 65 void set(int S, int T) { 66 this->S = S; 67 this->T = T; 68 f = new int[(T + 1)]; 69 le = new int[(T + 1)]; 70 mf = new int[(T + 1)]; 71 vis = new boolean[(T + 1)]; 72 pfill(vis, vis + T, false); 73 } 74 75 int spfa() { 76 queue<int> que; 77 pfill(f, f + T + 1, inf); 78 que.push(S); 79 f[S] = 0, le[S] = -1, mf[S] = inf; 80 while (!que.empty()) { 81 int e = que.front(); 82 que.pop(); 83 vis[e] = false; 84 for (int i = g.h[e], eu, w; ~i; i = g[i].nx) { 85 if (!g[i].r) 86 continue; 87 eu = g[i].ed, w = f[e] + g[i].c; 88 if (w < f[eu]) { 89 f[eu] = w, le[eu] = i, mf[eu] = min(mf[e], g[i].r); 90 if (!vis[eu]) { 91 vis[eu] = true; 92 que.push(eu); 93 } 94 } 95 } 96 } 97 if (f[T] == inf) 98 return inf; 99 int rt = 0; 100 for (int p = T, e; ~le[p]; p = g[e ^ 1].ed) { 101 e = le[p]; 102 g[e].r -= mf[T]; 103 g[e ^ 1].r += mf[T]; 104 rt += mf[T] * g[e].c; 105 } 106 return rt; 107 } 108 109 int min_cost() { 110 int rt = 0, delta; 111 while ((delta = spfa()) != inf) { 112 rt += delta; 113 // cerr << delta << ‘\n‘; 114 } 115 return rt; 116 } 117 } Graph; 118 119 int n; 120 int P, M, F, N, S; 121 int *require; 122 MapManager &g = Graph.g; 123 124 inline void init() { 125 scanf("%d", &n); 126 scanf("%d%d%d%d%d", &P, &M, &F, &N, &S); 127 require = new int[(n + 1)]; 128 g = MapManager(n << 1 | 1); 129 for (int i = 1; i <= n; i++) { 130 scanf("%d", require + i); 131 } 132 } 133 134 inline void solve() { 135 int T = n << 1 | 1; 136 Graph.set(0, T); 137 for (int i = 1; i <= n; i++) { 138 g.addArc(0, i, require[i], 0); 139 g.addArc(0, i + n, inf, P); 140 if (i < n) { 141 g.addArc(i, i + 1, inf, 0); 142 g.addArc(i + n, i + n + 1, inf, 0); 143 } 144 if (i + M <= n) 145 g.addArc(i, i + n + M, inf, F); 146 if (i + N <= n) 147 g.addArc(i, i + n + N, inf, S); 148 g.addArc(i + n, T, require[i], 0); 149 } 150 printf("%d\n", Graph.min_cost()); 151 } 152 153 int main() { 154 init(); 155 solve(); 156 return 0; 157 }

loj 6008 餐巾計劃 - 費用流