BZOJ 1061: [Noi2008]志愿者招募

news/2025/2/27 10:37:42

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\n", minCost());
142 }

 

@Author: YouSiki

 

转载于:https://www.cnblogs.com/yousiki/p/6276705.html


http://www.niftyadmin.cn/n/1536182.html

相关文章

Java经典算法汇总之冒泡排序

冒泡排序基本思想&#xff1a;在要排序的一组数中&#xff0c;对当前还未排好序的范围内的全部数&#xff0c;自上而下对相邻的两个数依次进行比较和调整&#xff0c;让较大的数往下沉&#xff0c;较小的往上冒。即&#xff1a;每当两相邻的数比较后发现它们的排序与排序要求相…

nrm管理npm源切换

nrm管理npm源切换 1. 安装nrm nrm -g install nrm2. 常用命令 这里的< 名称>可以使用镜像地址&#xff0c;也可以使用 nrm ls 输出的镜像的别名 nrm ls # 查看镜像列表 nrm current # 查看当前使用j镜像 nrm add <名称> <远程地址或私服地址> # 添加镜像…

React配置webpack多页应用打包失败,报错Cannot read property ‘filter’ of undefined解决方案

React多页配置&#xff0c;Cannot read property ‘filter’ of undefined错误分析配置好react多页应用后&#xff0c;yarn build打包运行, 控制台报错错误定位错误分析1. 打印 entrypoints 对象2. 为什么会没有 main 属性原来的entry属性修改后的 entry 属性错误原因解决方法配…

Link方式导入java项目

一、环境说明 我用的是eclipse3.3.2&#xff0c;并安装了myeclipse的插件。 二、工程文件说明 一共三个文件夹&#xff1a; javacode&#xff1a;存放Java源文件&#xff0c;包含多个子文件夹&#xff0c;每个子文件夹表示一个单独的模块&#xff0c;里面存放的才是真正的源文件…

nvm设置全局共享的npm版本

设置全局npm版本 因为 nvm 管理不同的Node版本&#xff0c;每个Node版本对应一个 npm 版本&#xff0c;不能共享同一个npm&#xff0c;不同Node版本都需要安装一堆一样的包&#xff0c;所以需要有一个 npm 可以让各个版本的 Node 共用。【三步走】 # 1. 配置npm下载包时的全局…

微软雅黑 css

body {font-family:"Microsoft YaHei",Arial,Helvetica,sans-serif,"SimSun"; }转载于:https://www.cnblogs.com/xdea/p/6286244.html

线段树扫描线 HDU 1542

n个矩形 问他们覆盖的面积重复的就算一次 x数组存线段 然后根据横坐标排一下 z 线段树 l - r 就是1 ~ 2*n #include<stdio.h> #include<algorithm> #include<string.h>using namespace std;#define MAXN 110 struct line {double x,y1,y2;int flag; }x[MA…

jquery中,使用append增加元素时,该元素的绑定监听事件失效

举例&#xff1a;如果在一个<div id"resultArea"></div>中&#xff0c;通过append添加一个id"checkOutTip"的文本框&#xff0c;监听值变化。常用的直接$("Selector").on("eventType",function(){})监听事件函数不起作用&…