洛谷P3980 [NOI2008]志愿者招募——费用流

  • 题目介绍
    • 题目描述
    • 输入格式
    • 输出格式
    • 测试样例
  • 题解
  • 代码

题目介绍

题目描述

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

输入格式

第一行包含两个整数 n,m,表示完成项目的天数和可以招募的志愿者的种类。接下来的一行中包含 n 个非负整数,表示每天至少需要的志愿者人数。 接下来的 m行中每行包含三个整数 si,ti,ci,含义如上文所述。为了方便起见,我们可以认为每类志愿者的数量都是无限多的。
1≤n≤1000,1≤m≤10000,题目中其他所涉及的数据均不超过 2^31−1。

输出格式

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

测试样例

输入 #1
3 3
2 3 4
1 2 2
2 3 5
3 3 2

输出#1
14

题解

参考链接: dalao博客.
看起来感觉是最小费用流,但不知如何建网络。参考了大佬们的题解也只能是理解了这种建网络方式,还是要多做题。
先建网络如下,再解释:

  1. 对第i天需要的志愿者数量为ai,在第i天和第i+1天连边,容量INF-ai,费用0;
  2. 对第i种志愿者(si,ti,ci),在si和ti+1间连边,容量INF,费用ci;
  3. 最后超级源点对第1天连边、第N+1天对超级汇点连边,容量都INF,费用都为0.

以上第3步,使得最终流经全网络的网络流流量为INF。对于第i天和第i+1天,为了令其间所有边(包括连接i和i+1边、以及跨过的边)总容量也为INF,则必然先流经直接连接的费用为0的边(对费用无贡献),对于不足的容量a[i] 则通过志愿者流过,即流经第2步所建边。

该建网络方式具有特点:以时间顺序流经网络,体现将志愿者的工作覆盖范围。因此从源点向汇点跑一遍最小费用最大流即可。

代码

#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;/*
网络流建边:
(1)第i天和第i+1天建边,容量INF-a[i],费用0;
(2)第i种志愿者在s[t]和t[i]间建边,容量INF,费用c[i]
(3)源点和第1天建边容量INF,费用0;第N+1天和T建边,容量INF,费用0首先以上建边方式保证了流经网络总流量为INF;
对于第i和第i+1天,其间所有边(包括直接连接i和i+1,与跨过i和i+1)总流量也必然为INF;
对于INF-a[i]优先选费用为0的边,剩下走志愿者;对于覆盖这一范围志愿者就无需再增广。
最终流经志愿者的流量满足题目要求的每日的需求量。 跑最小费用最大流即可。
*/
typedef long long ll;
const int maxn=1010;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int inf=0x3f;
class Edge{public:ll to,cap,cost,nxt,rev;
};
int head[maxn];
Edge edge[maxn<<5];
int cnt=1;
int N,M,a,S,T;void add(ll u,ll v, ll cap, ll cost){edge[cnt].to=v;edge[cnt].cap=cap;edge[cnt].cost=cost;edge[cnt].nxt=head[u];edge[cnt].rev=cnt+1; head[u]=cnt++;edge[cnt].to=u;edge[cnt].cap=0; edge[cnt].cost=-cost;edge[cnt].nxt=head[v];edge[cnt].rev=cnt-1; head[v]=cnt++;
}bool vis[maxn<<1];
int pre[maxn<<1],preEdge[maxn<<1];
ll dis[maxn<<1];
ll flow[maxn<<1];
ll h[maxn<<1];bool Dkjistra(int S, int T){memset(vis,false,sizeof(vis));memset(dis, inf, sizeof(dis));                     //dis为引入势之后的最短距离,h为真实的距离       memset(flow, inf, sizeof(flow)); priority_queue<pair<int, int> > que;dis[S] = 0;que.push(make_pair(-dis[S], S) );                  //优先队列,注意取负值 while(!que.empty() ){int u = que.top().second;  que.pop();if(vis[u]) continue;                           //因每次更新都需要入队,需判断是否访问过 vis[u] = true;for(int i=head[u]; i; i=edge[i].nxt){Edge &e = edge[i];if(vis[e.to]) continue;if(e.cap>0 && dis[e.to] > dis[u] + e.cost + h[u] - h[e.to]){dis[e.to] = dis[u] + e.cost + h[u] - h[e.to];pre[e.to] = u;                              //记录前驱结点 preEdge[e.to] = i;                          //记录前驱边 flow[e.to] = min(flow[u], e.cap); que.push(make_pair(-dis[e.to], e.to));      //入队 }} }
//             h[i]为真实最短路权值for(int i=1;i<=T;i++) h[i] += dis[i];                   return dis[T] != INF;
} void MCMF(){ll maxflow = 0; ll mincost = 0; while(Dkjistra(S, T)){                                   //将Dinic算法的分层找最短增广路,改为Dijkstra找费用最低路径 maxflow += flow[T];mincost += flow[T] * h[T];                     //h[T]为从S->T路径上单位流量总的cost int now = T;while(now!=S){                                   //从汇点回溯到源点 Edge &e = edge[preEdge[now]]; e.cap -= flow[T];                              //更新残余网络 edge[e.rev].cap += flow[T];now = pre[now];}}printf("%lld\n",mincost);
} int main(){scanf("%d%d",&N,&M);S=N+2;T=N+3;for(int i=1;i<=N;i++){scanf("%d",&a);add(i,i+1,INF-a,0);} add(S,1,INF,0);add(N+1,T,INF,0);int s,t;for(int i=1;i<=M;i++){scanf("%d%d%d",&s,&t,&a);add(s,t+1,INF,a);}MCMF();
}

最后:
多做题、多思考建网络方式

洛谷P3980 志愿者招募——费用流相关推荐

  1. 洛谷P3980 志愿者招募

    题意:懒得写了...... 解: 一开始想的是每天建点,每种人建点,然后连边费用流,发现一个人可以管辖多天,不好处理. 回想起了网络流24题中的"最长k可重线段集","最 ...

  2. [Bzoj1061][Noi2008]志愿者招募(费用流)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1061 一开始疯狂想dp,然后队友走过来瞄一眼就告诉我像费用流,菜的真实,jpg. 一种比 ...

  3. 洛谷 P4015 运输问题(费用流)

    运输问题 题目描述 W W W 公司有 m m m 个仓库和 n n n 个零售商店.第 i i i 个仓库有 a i a_i ai​ 个单位的货物:第 j j j 个零售商店需要 b j b_j b ...

  4. bzoj 1061 志愿者招募 费用流

    详见BYV的博客,写的非常全面https://www.byvoid.com/blog/noi-2008-employee /************************************** ...

  5. 家园 / 星际转移问题(洛谷P2754 分层图+最大流)

    再一次感觉网络流太神奇了qwq 题目链接:[星际转移问题](P4009 汽车加油行驶问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)) 受到之前那道[汽车加油行驶问题](P400 ...

  6. 洛谷 - P3980 [NOI2008]志愿者招募(最小费用最大流+思维建边)

    题目链接:点击查看 题目大意:现在有n天需要志愿者,每一天需要招募的人数是Ai个人,现在有m类志愿者,每类志愿者可以在[l,r]天内被招募,需要花费的代价为Ci,现在需要安排一种招募方式,可以使得总花 ...

  7. [SCOI2007]修车,洛谷P2053,最小费用最大流

    正题 给出m个师傅,n台车,并给出每个师傅各个车的时间,现在要使得,n辆车一起来,等待时间最短. 我们来观察一个师傅所消耗的等待时间.m个师傅所消耗的总等待时间就是车主的总等待时间. 对于第a个师傅, ...

  8. 洛谷4014最大/小费用最大流

    题目:https://www.luogu.org/problemnew/show/P4014 #include<iostream> #include<cstdio> #incl ...

  9. 洛谷P3254 圆桌问题(最大流)

    题意 $m$个不同单位代表参加会议,第$i$个单位有$r_i$个人 $n$张餐桌,第$i$张可容纳$c_i$个代表就餐 同一个单位的代表需要在不同的餐桌就餐 问是否可行,要求输出方案 Sol 比较zz ...

最新文章

  1. scrum项目管理_Scrum,用于初创企业(或针对该项目的任何项目)
  2. Linux 4.18 内核新补丁移除了Lustre 文件系统
  3. KVC/KVO 使用细节和调用顺序
  4. 【百度地图API】如何制作多途经点的线路导航——驾车篇
  5. Xshell更改命令提示符以及背景配色
  6. 使用固态存储SSD或PCIe卡
  7. 在图形中使用指定字体
  8. fundamental-react在POC中的一个应用
  9. Ajax — 大事件项目(第一天)
  10. python数组元素复制_python的numpy数组 的复制问题?
  11. Spring MVC数据绑定和表单标签的应用(附带实例)
  12. 对象序列化和反序列化是怎么回事
  13. 蓝桥杯 ADV-84 算法提高 图形输出
  14. LeetCode Search a 2D Matrix
  15. elasticsearch的keyword与text的区别
  16. IDEA黑色主题Darcula主题看不到鼠标指针
  17. python 网格策略_『量化经典策略』网格策略
  18. delphi 控件大全(确实很全)
  19. ebs 供应商地点信息_EBS R12使用接口表往已存在的供应商地址下创建新的地点
  20. 完美删除EISA硬盘隐藏分区(OEM隐藏分区)

热门文章

  1. php 获取qq头像,php获取QQ头像并显示的方法_PHP教程
  2. 恐鬼症服务器显示不出来怎么办,Phasmophobia恐鬼症10月29日更新修复内容介绍
  3. Linux基础命令 userdel彻底删除一个用户
  4. PS 图像调整算法——亮度调整
  5. c语言点滴 书签 pdf,C语言程序设计(详细书签)文字版.pdf
  6. 怎样使用Photoshop 的操控变形功能
  7. 相差400!OPPO、华为千元5G手机对比,谁的实力更硬核?
  8. 基础-Eclipse 教程
  9. Zabbix搭建部署与概述(一)
  10. python不识别pip命令