zoukankan      html  css  js  c++  java
  • BZOJ 1061: [Noi2008]志愿者招募

    1061: [Noi2008]志愿者招募

    Time Limit: 20 Sec  Memory Limit: 162 MB
    Submit: 4091  Solved: 2496
    [Submit][Status][Discuss]

    Description

      申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难
    题:为即将启动的奥运新项目招募一批短期志愿者。经过估算,这个项目需要N 天才能完成,其中第i 天至少需要
    Ai 个人。 布布通过了解得知,一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用
    是每人Ci 元。新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者,但这
    并不是他的特长!于是布布找到了你,希望你帮他设计一种最优的招募方案。

    Input

      第一行包含两个整数N, M,表示完成项目的天数和可以招募的志愿者的种类。 接下来的一行中包含N 个非负
    整数,表示每天至少需要的志愿者人数。 接下来的M 行中每行包含三个整数Si, Ti, Ci,含义如上文所述。为了
    方便起见,我们可以认为每类志愿者的数量都是无限多的。

    Output

      仅包含一个整数,表示你所设计的最优方案的总费用。

    Sample Input

    3 3
    2 3 4
    1 2 2
    2 3 5
    3 3 2

    Sample Output

    14

    HINT

    1 ≤ N ≤ 1000,1 ≤ M ≤ 10000,题目中其他所涉及的数据均 不超过2^31-1。

    Source

     
    [Submit][Status][Discuss]

    无源汇最小费用可行流

    原本无源汇的网络是这个样子的:

    有$N+1$个点,代表每一天,其中有$N$条边连接,形如$<i,i+1,need_{i},inf,0>$,括号内分别为出点,入点,最小流量,最大流量,费用。这样就限制了每一天的志愿者人数最小值。

    然后对于一类志愿者,如果设开始时间为$st$,终止时间为$ed$,费用为$ct$,那么连边$<ed+1,st,0,inf,ct>$,代表至少选0个这类志愿者(就是不选),至多inf(没有上限),选择一个费用为$ct$。

    在这个网络上求解无源汇的最小费用可行流即可。

      1 #include <cstdio>
      2 #include <cstring>
      3 
      4 inline char Char(void)
      5 {
      6     static const short siz = 1024;
      7     
      8     static char buf[siz];
      9     static char *hd = buf + siz;
     10     static char *tl = buf + siz;
     11     
     12     if (hd == tl)
     13         fread(hd = buf, 1, siz, stdin);
     14     
     15     return *hd++;
     16 }
     17 
     18 inline int Int(void)
     19 {
     20     int ret = 0, neg = 0, c = Char();
     21     
     22     for (; c < 48; c = Char())
     23         if (c == '-')neg ^= true;
     24     
     25     for (; c > 47; c = Char())
     26         ret = ret * 10 + c - '0';
     27     
     28     return neg ? -ret : ret;
     29 }
     30 
     31 const int mxn = 2005;
     32 const int mxm = 20005;
     33 const int siz = 2000005;
     34 const int inf = 1000000007;
     35 
     36 int n, m, need[mxn], st[mxm], ed[mxm], ct[mxm], cnt[mxn];
     37 
     38 int s, t;
     39 int hd[siz];
     40 int to[siz];
     41 int fl[siz];
     42 int vl[siz];
     43 int nt[siz];
     44 
     45 inline void add(int u, int v, int f, int w)
     46 {
     47     static int tot = 0, init = 1;
     48     
     49     if (init)memset(hd, -1, sizeof(hd)), init = 0;
     50     
     51     nt[tot] = hd[u]; to[tot] = v; fl[tot] = f; vl[tot] = +w; hd[u] = tot++;
     52     nt[tot] = hd[v]; to[tot] = u; fl[tot] = 0; vl[tot] = -w; hd[v] = tot++;
     53 }
     54 
     55 int pre[mxn];
     56 int dis[mxn];
     57 
     58 inline bool spfa(void)
     59 {
     60     static int que[siz];
     61     static int inq[mxn];
     62     static int head, tail;
     63     
     64     for (int i = s; i <= t; ++i)dis[i] = inf;
     65     memset(inq, 0, sizeof(inq));
     66     head = 0, tail = 0;
     67     
     68     que[tail++] = s;
     69     pre[s] = -1;
     70     dis[s] = 0;
     71     
     72     while (head != tail)
     73     {
     74         int u = que[head++], v; inq[u] = 0;
     75         
     76         for (int i = hd[u]; ~i; i = nt[i])
     77             if (fl[i] && dis[v = to[i]] > dis[u] + vl[i])
     78             {
     79                 dis[v] = dis[u] + vl[i]; pre[v] = i ^ 1;
     80                 if (!inq[v])inq[que[tail++] = v] = 1;
     81             }
     82     }
     83     
     84     return dis[t] < inf;
     85 }
     86 
     87 inline int minCost(void)
     88 {
     89     int cost = 0;
     90     
     91     while (spfa())
     92     {
     93         int flow = inf;
     94         
     95         for (int i = pre[t]; ~i; i = pre[to[i]])
     96             if (flow > fl[i ^ 1])flow = fl[i ^ 1];
     97         
     98         for (int i = pre[t]; ~i; i = pre[to[i]])
     99             fl[i] += flow, fl[i ^ 1] -= flow;
    100             
    101         cost += flow * dis[t];
    102     }
    103     
    104     return cost;
    105 }
    106 
    107 signed main(void)
    108 {
    109     n = Int();
    110     m = Int();
    111     
    112     for (int i = 1; i <= n; ++i)
    113         need[i] = Int();
    114     
    115     for (int i = 1; i <= m; ++i)
    116     {
    117         st[i] = Int();
    118         ed[i] = Int();
    119         ct[i] = Int();
    120     }
    121     
    122     s = 0, t = n + 2;
    123     
    124     for (int i = 1; i <= n; ++i)
    125     {
    126         add(i, i + 1, inf, 0);
    127         
    128         cnt[i] -= need[i];
    129         cnt[i + 1] += need[i];
    130     }
    131     
    132     for (int i = 1; i <= m; ++i)
    133         add(ed[i] + 1, st[i], inf, ct[i]);
    134     
    135     for (int i = 1; i <= n + 1; ++i)
    136         if (cnt[i] < 0)
    137             add(i, t, -cnt[i], 0);
    138         else if (cnt[i] > 0)
    139             add(s, i, +cnt[i], 0);
    140     
    141     printf("%d
    ", minCost());
    142 }

    @Author: YouSiki

  • 相关阅读:
    Unity跳转场景进度条制作教程(异步加载)
    Unity LOD-Level of Detail(多层次细节)用法教程
    Unity查找物体的子物体、孙物体
    Unity导航系统Navigation使用教程
    Unity物品栏、商城3D物品的显示插件
    VIM编辑器常用命令
    linux系统常用命令
    CRITICAL:yum.cli:Config Error: Error accessing file for config file:///etc/yum.conf
    linux下使用tar命令详解
    Linux之安装软件
  • 原文地址:https://www.cnblogs.com/yousiki/p/6276705.html
Copyright © 2011-2022 走看看