• loj 6008 餐巾计划


    题目传送门

      传送门

    题目大意

      (经典题还不知道题意?)

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

      设$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 << '
    ';
    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
    ", Graph.min_cost());
    151 }
    152 
    153 int main() {
    154     init();
    155     solve();
    156     return 0;
    157 }
  • 相关阅读:
    一个非常简单的IMPDP事儿
    在线修改redo日志大小
    OGG-02803 Encountered a Data Guard role transition
    Linux新加磁盘挂载和重启自动挂载
    ORACLE字符集修改ORA-02374ORA-12899ORA-02372
    oracle nid修改dbname
    python模块PIL-获取带噪点噪线的随机验证码
    mysql两个重要的日志redolog和binlog
    在Spring中使用数据验证组件hibernate-validator
    SpringMVC接收请求参数所有方式总结
  • 原文地址:https://www.cnblogs.com/yyf0309/p/10193319.html
Copyright © 2020-2023  润新知