码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 1283 序列 - 费用流

时间:2018-12-30 02:42:34      阅读:144      评论:0      收藏:0      [点我收藏+]

标签:round   最大的   turn   last   operator   +=   inline   color   fill   

题目传送门

  传送门

题目大意

  给定一个长度为$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 }

bzoj 1283 序列 - 费用流

标签:round   最大的   turn   last   operator   +=   inline   color   fill   

原文地址:https://www.cnblogs.com/yyf0309/p/10198124.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!