题意:最多1000天 每天需要至少ai个工人施工 有10000种工人可以雇佣

   每种工人可以工作si到ti天 雇佣一个的花费是ci 问怎样安排使得施工花费最少

思考:最直白的建模方式 就是每种工人可以和他能工作的天 连边

   但是这样就引出了一个一对多的问题 一种工人对他所连的所有天 贡献是一样的

   也就是说他流向和他连的天的 流量应该都是一样的 但是网络流显然是做不到这一点

  

   于是我们重新思考 发现每种工人其实就是一种区间覆盖 那么我们考虑差分的思想

   把每相邻两天连起来 表示这种工人在第i天工作了后 跑到第i+1天去工作了

   因为每种工人最多工作到ti天 所以我们要考虑某种方式在ti+1天把si流进来的流量放出去 他不能对ti+1天有贡献

   然后就不会了....

题解:把每一天当作点 今天向明天连一条 容量INF-ai 花费0的边

   对于每种工人 从si天向ti+1天 连 容量为INF 花费为ci的边

   s连1 容量INF花费0  n+1连t 容量INF 花费0

   跑一遍最大流 因为一定有完成施工的方案 所以能满流 得到的最小花费就是答案

   为什么每两天之间的容量是INF-ai 表示今天需要至少ai的流量从带权边补足到INF

#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f; int n, m, cnt, mincost, s, t;
struct node {
int to, nex, val, cost;
}E[30005];
int head[1005];
int cur[1005];
int a[1005]; void addedge(int x, int y, int va, int cos) {
E[++cnt].to = y; E[cnt].nex = head[x]; head[x] = cnt; E[cnt].val = va; E[cnt].cost = cos;
E[++cnt].to = x; E[cnt].nex = head[y]; head[y] = cnt; E[cnt].val = 0; E[cnt].cost = -cos;
} int dis[1005], inque[1005], vis[1015];
bool spfa() {
for(int i = 1; i <= t; i++) dis[i] = INF, inque[i] = 0, cur[i] = head[i];
queue<int> que; que.push(s);
dis[s] = 0; inque[s] = 1; while(!que.empty()) {
int u = que.front(); que.pop();
inque[u] = 0; for(int i = head[u]; i; i = E[i].nex) {
int v = E[i].to;
if(E[i].val && dis[v] > dis[u] + E[i].cost) {
dis[v] = dis[u] + E[i].cost;
if(!inque[v]) {
inque[v] = 1;
que.push(v);
}
}
}
}
return dis[t] != INF;
} int dfs(int x, int flow) {
if(x == t) {
vis[t] = 1;
return flow;
} vis[x] = 1;
int used = 0, rflow = 0;
for(int i = cur[x]; i; i = E[i].nex) {
cur[x] = i;
int v = E[i].to;
if(E[i].val && dis[v] == dis[x] + E[i].cost && (!vis[v] || v == t)) {
if(rflow = dfs(v, min(E[i].val, flow - used))) {
used += rflow;
E[i].val -= rflow;
E[i ^ 1].val += rflow;
mincost += rflow * E[i].cost;
if(used == flow) break;
}
}
}
return used;
} void dinic() {
mincost = 0;
while(spfa()) {
vis[t] = 1;
while(vis[t]) {
memset(vis, 0, sizeof(int) * (t + 1));
dfs(s, INF);
}
}
} int main() {
cnt = 1;
scanf("%d%d", &n, &m);
s = n + 2; t = s + 1;
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = 1; i <= m; i++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
addedge(a, b + 1, INF, c);
}
for(int i = 1; i <= n; i++) addedge(i, i + 1, INF - a[i], 0);
addedge(s, 1, INF, 0); addedge(n + 1, t, INF, 0);
dinic();
printf("%d\n", mincost);
return 0;
}

P3980 [NOI2008]志愿者招募 (费用流)的更多相关文章

  1. P3980 [NOI2008]志愿者招募 费用流 (人有多大胆地有多大产

    https://www.luogu.org/problemnew/show/P3980 感觉费用流比网络流的图更难想到,要更大胆.首先由于日期是连续的,所以图中的点是横向排列的. 这道题有点绕道走的意 ...

  2. BZOJ 1061: [Noi2008]志愿者招募 费用流

    1061: [Noi2008]志愿者招募 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1061 Description 申奥成功后,布布 ...

  3. [BZOJ1061] [Noi2008] 志愿者招募 (费用流)

    Description 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难 题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能 ...

  4. [NOI2008]志愿者招募 (费用流)

    大意: $n$天, 第$i$天要$a_i$个志愿者. $m$种志愿者, 每种无限多, 第$i$种工作时间$[s_i,t_i]$花费$c_i$, 求最少花费. 源点$S$连第一天, 容量$INF$ 第$ ...

  5. Vijos1825 NOI2008 志愿者招募 费用流

    Orz ByVoid大神的题解:https://www.byvoid.com/blog/noi-2008-employee/ 学习网络流建图的好题,不难想到线性规划的模型,不过利用模型的特殊性,结合网 ...

  6. 【洛谷】P3980 [NOI2008]志愿者招募

    [洛谷]P3980 [NOI2008]志愿者招募 我居然现在才会用费用流解线性规划-- 当然这里解决的一类问题比较特殊 以式子作为点,变量作为边,然后要求就是变量在不同的式子里出现了两次,系数一次为+ ...

  7. 从多种角度看[BZOJ 1061] [NOI 2008]志愿者招募(费用流)

    从多种角度看[BZOJ 1061] [NOI 2008]志愿者招募(费用流) 题面 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难题:为即将启动的奥运 ...

  8. [NOI2008][bzoj1061] 志愿者招募 [费用流+巧妙的建图]

    题面 传送门 思路 引入:网络流? 看到这道题,第一想法是用一个dp来完成决策 但是,显然这道题的数据并不允许我们进行dp,尤其是有10000种志愿者的情况下 那么我们就要想别的办法来解决: 贪心?这 ...

  9. luogu P3980 [NOI2008]志愿者招募

    传送门 网络流又一神仙套路应用 首先考虑列不等式,设\(x_i\)为第i种人的个数,记\(b_{i,j}\)为第i种人第j天是否能工作,那么可以列出n个不等式,第j个为\(\sum_{i=1}^{m} ...

随机推荐

  1. swack的wiki站上线

    swack的个人wiki网址:www.swack.cn [服务器破旧,速度较慢,见谅!]

  2. 【LeetCode】365.水壶问题

    题目描述 解题思路 思路一:裴蜀定理-数学法 由题意,每次操作只会让桶里的水总量增加x或y,或者减少x或y,即会给水的总量带来x或y的变化量,转为数字描述即为:找到一对整数a,b使得下式成立: ax+ ...

  3. linux硬盘分区和fdisk命令

    分区的几个概念 硬盘分区有三种,主分区.扩展分区.逻辑分区.一个硬盘主分区至少有1个,最多4个,扩展分区可以没有,最多1个.且主分区+扩展分区总共不能超过4个.逻辑分区可以有若干个.在windows下 ...

  4. Cloudera Manager添加主机节点

    为了监控方便,想把研发环境中的主机节点都纳入Cloudera Manager的管理中,这样在遇到问题时可方便的查看主机的硬件资源情况. 添加主机节点有多种方式,由于我是离线工作,所以选择rpm包的方式 ...

  5. .NET 云原生架构师训练营(模块二 基础巩固 Scrum 团队)--学习笔记

    2.7.3 Scrum 团队 理想的环境 团队章程 如何组建 Scrum 团队 产品待办事项列表 用户故事 敏捷开发流程 理想的环境 5-9人 100% 跨职能 在一起 自组织 自组织 目标 授权 沟 ...

  6. Api文档自动生成工具

    java开发,根据代码自动生成api接口文档工具,支持RESTful风格,今天我们来学一下api-doc的生成 作者:互联网编程. 欢迎投稿,一起交流技术 https://www.jianshu.co ...

  7. 小试牛刀ElasticSearch大数据聚合统计

    ElasticSearch相信有不少朋友都了解,即使没有了解过它那相信对ELK也有所认识E即是ElasticSearch.ElasticSearch最开始更多用于检索,作为一搜索的集群产品简单易用绝对 ...

  8. 如何在 crontab 中让 source ~/.bashrc 生效

    cron 是许多类 Unix 操作系统中都自带的用来调度定时任务的工具,定时任务的配置是写在 crontab 文件中的,但是 crontab 文件不允许直接编辑,一般都是通过命令 crontab -e ...

  9. 求得二叉搜索树的第k小的元素

    求得二叉搜索树的第k小的元素 给定一个二叉搜索树,编写一个函数 kthSmallest 来查找其中第 k 个最小的元素. 须知:二叉搜索树,又叫二叉排序树,二叉查找树.特点是:左子树的所有元素都小于等 ...

  10. 获取网页url中的参数

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...