1. 程式人生 > >bzoj 1283 序列 - 費用流

bzoj 1283 序列 - 費用流

題目傳送門

  傳送門

題目大意

  給定一個長度為$n$的序列,要求選出一些數使得原序列中每$m$個連續的數中不超過$K$個被選走。問最大的可能的和。

  感覺建圖好妙啊。。

  考慮把問題轉化成選$m$次數,每次選出一個子序列, 要求兩次選擇的數的下標差至少為$m$。

  這個很容易建圖就能做。$i$向$\min\{T, i + m\}$連邊,容量為1,費用為$a_i$。$i$向$i + 1$連邊容量為1,費用為0.

Code

  1 /**
  2  * bzoj
  3  * Problem#1283
  4  * Accepted
  5
* Time: 232ms 6 * Memory: 1436k 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 typedef class Graph { 56 public: 57 int S, T; 58 MapManager g; 59 60 int *le; 61 int *f, *mf; 62 boolean *vis; 63 64 Graph() { } 65 // be sure T is the last node 66 Graph(int S, int T) { 67 this->S = S; 68 this->T = T; 69 f = new int[(T + 1)]; 70 le = new int[(T + 1)]; 71 mf = new int[(T + 1)]; 72 vis = new boolean[(T + 1)]; 73 pfill(vis, vis + T, false); 74 } 75 76 int spfa() { 77 queue<int> que; 78 pfill(f, f + T + 1, -inf); 79 que.push(S); 80 f[S] = 0, le[S] = -1, mf[S] = inf; 81 while (!que.empty()) { 82 int e = que.front(); 83 que.pop(); 84 vis[e] = false; 85 for (int i = g.h[e], eu, w; ~i; i = g[i].nx) { 86 if (!g[i].r) 87 continue; 88 eu = g[i].ed, w = f[e] + g[i].c; 89 if (w > f[eu]) { 90 f[eu] = w, le[eu] = i, mf[eu] = min(mf[e], g[i].r); 91 if (!vis[eu]) { 92 vis[eu] = true; 93 que.push(eu); 94 } 95 } 96 } 97 } 98 if (f[T] == -inf) 99 return inf; 100 int rt = 0; 101 for (int p = T, e; ~le[p]; p = g[e ^ 1].ed) { 102 e = le[p]; 103 g[e].r -= mf[T]; 104 g[e ^ 1].r += mf[T]; 105 rt += mf[T] * g[e].c; 106 } 107 return rt; 108 } 109 110 int max_cost() { 111 int rt = 0, delta; 112 while ((delta = spfa()) != inf) { 113 rt += delta; 114 // cerr << delta << '\n'; 115 } 116 return rt; 117 } 118 } Graph; 119 120 int n, m, k; 121 122 inline void solve() { 123 scanf("%d%d%d", &n, &m, &k); 124 Graph graph(0, n + 1); 125 MapManager& g = graph.g; 126 k = min(k, m); 127 g = MapManager(n + 1); 128 g.addArc(0, 1, k, 0); 129 for (int i = 1, x; i <= n; i++) { 130 scanf("%d", &x); 131 g.addArc(i, min(n + 1, i + m), 1, x); 132 g.addArc(i, i + 1, k, 0); 133 } 134 printf("%d\n", graph.max_cost()); 135 } 136 137 int main() { 138 solve(); 139 return 0; 140 }