题目链接:点击查看

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

题目分析:看了题解后看大佬们分析的线性规划以及动态规划的解法都是一脸懵逼的,因为是随着网络流的标签进入到这个题目,所以自然要往网络流的方向去靠拢,看到这个题可以将模型抽象出来,发现是关于区间覆盖的问题,之前网络流24题里有一个最长k可重区间集问题,好像可以用那个模型套一下试试,因为招募志愿者,只需要支付一次费用就可以享受[l,r]内所有天的服务,所以我们理所应当建一条边从l到r+1,流量为无穷大,花费为对应的代价,那么多余的志愿者该怎么办呢,可以模仿可重区间集的那个问题的思想,开一条特殊的“通道”,将多余的志愿者流过去而不影响最终花费,当然我们需要将源点连向第一个点,同时最后一个点连向汇点,在处理多余志愿者时,我们因为只需要Ai个志愿者,所以-Ai个志愿者是多余的,换句话说,如果我们一共有10个人,现在需要a个志愿者,那么10-a个志愿者是多余的,同理,只不过这里的10个人我们视为0就会出现-Ai这样的取值了,不过在建边时正向边的流量必须非负,这样我们自然可以加上一个很大的数,用来限流即可,具体建边方法如下:

  1. 源点->第一个点,流量为inf,花费为0
  2. 每个点->下一个点,流量为inf-Ai,花费为0
  3. 志愿者开始日期->志愿者结束日期+1,流量为inf,花费为Ci
  4. 最后一个点->汇点,流量为inf,花费为0

最后解释一下为什么让多余的志愿者流过去可以这样操作,因为我们源点和汇点的流量都设置为了无穷大,所以整张图最后跑出来的最大流一定是无穷大的,既然每个点到下一个点的这一条道路我们将其用作给多余的志愿者使用的道路,而对于每条这样的边,其权值都会比inf少Ai,但既然要保证最后的最大流为inf,少掉的这Ai的流量当然要从带权值的边上跑才行,也就达到了限流的目的

说在最后,其实这个题目正常人第一反应都是源点到志愿者建边,志愿者再到可影响的天数建边,但是会发现这是一个典型的网络流无法解决的“一对多”的模式,也就是志愿者的一个单位的流量会影响多个天数,所以我们必须转换思维模式,才能进行求解

代码:

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e3+100;//点const int M=1e5+100;//边struct Edge
{int to,w,cost,next;
}edge[M];int head[N],cnt;void addedge(int u,int v,int w,int cost)
{edge[cnt].to=v;edge[cnt].w=w;edge[cnt].cost=cost;edge[cnt].next=head[u];head[u]=cnt++;edge[cnt].to=u;edge[cnt].w=0;edge[cnt].cost=-cost;edge[cnt].next=head[v];head[v]=cnt++;
}int d[N],incf[N],pre[N];bool vis[N];bool spfa(int s,int t)
{memset(d,inf,sizeof(d));memset(vis,false,sizeof(vis));memset(pre,-1,sizeof(pre));queue<int>q;q.push(s);vis[s]=true;incf[s]=inf;d[s]=0;while(!q.empty()){int u=q.front();q.pop();vis[u]=false;for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;int w=edge[i].w;int cost=edge[i].cost;if(!w)continue;if(d[v]>d[u]+cost){d[v]=d[u]+cost;pre[v]=i;incf[v]=min(incf[u],w);if(!vis[v]){vis[v]=true;q.push(v);}}}}return pre[t]!=-1;
}int update(int s,int t)
{int x=t;while(x!=s){int i=pre[x];edge[i].w-=incf[t];edge[i^1].w+=incf[t];x=edge[i^1].to;}return d[t]*incf[t];
}void init()
{memset(head,-1,sizeof(head));cnt=0;
}int solve(int st,int ed)
{int ans=0;while(spfa(st,ed))ans+=update(st,ed);return ans;
}int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);init();int n,m,st=N-1,ed=st-1;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){int num;scanf("%d",&num);addedge(i,i+1,inf-num,0);}while(m--){int u,v,w;scanf("%d%d%d",&u,&v,&w);addedge(u,v+1,inf,w);}addedge(st,1,inf,0);addedge(n+1,ed,inf,0);printf("%d\n",solve(st,ed));return 0;
}

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

  1. 洛谷 - P1251 餐巾计划问题(最小费用最大流+思维建边)

    题目链接:点击查看 题目大意:给出n天每天所需要的新餐巾的数量,现在有多种方式可以获得新餐巾,问如何运营能使花费最少: 直接购买,花费为cost 将脏餐巾送到快洗部,需要洗t1天,花费为c1 将脏餐巾 ...

  2. [BZOJ1061] [NOI2008] 志愿者招募 - 最小费用最大流

    大部分内容转自: BYVOID - NOI2008 志愿者招募  如果讲道理的话,就是说我们抽象一下这个模型--然后每条费用边就是连接起始日期和结束日期的边,也就是说这条边上的流量增加1,就要增加一个 ...

  3. BZOJ 1061: [Noi2008]志愿者招募 最小费用最大流

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

  4. 洛谷 - P4016 负载平衡问题(最小费用最大流)

    题目链接:点击查看 题目大意:有n个仓库分布在一个环形的区域,现在每个仓库可以与相邻的两个仓库转移货物,问最少需要操作多少次才能让每个仓库的货物都达到平衡 题目分析:达到平衡的意思其实就是都等于平均值 ...

  5. 洛谷 P2053 [SCOI2007]修车 网络流 最小费用最大流 Dinic+Spfa

    题目链接: https://www.luogu.com.cn/problem/P2053 思路参考博客: https://www.luogu.com.cn/blog/a23333/solution-p ...

  6. CodeForces - 863F Almost Permutation(最小费用最大流+思维建边)

    题目链接:点击查看 题目大意:给出n个限制,每个限制分为两种类型: 1 l r val:区间[l,r]内的数都大于等于val 2 l r val:区间[l,r]内的数都小于等于val 并且规定每个数出 ...

  7. 洛谷 P3381 【模板】最小费用最大流

    题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行包含四个正整数\(N.M.S.T\) ...

  8. 洛谷 3381 【模板】最小费用最大流

    https://www.luogu.org/problem/show?pid=3381 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流 ...

  9. 洛谷P3381 【模板】最小费用最大流

    传送门 费用流板子 细节真多--一个边的flow和点的flow分不清--还有往回减流的时候应该减去flow[t]-- 1 //minamoto 2 #include<iostream> 3 ...

最新文章

  1. OVS对VXLAN解封包(二)
  2. r语言可以写c程序吗,[求助]R一般用什么写程序?
  3. 爱我少一点,我请求你
  4. python3类的继承详解_python3中类的继承以及self和super的区别详解
  5. 查询ElasticSearch:用SQL代替DSL
  6. 输出字符串引用名java_将方法名称作为字符串给出时,如何调用Java方法?
  7. 《C#并发编程经典实例》学习笔记—2.1 暂停一段时间
  8. 100条常用SQL语句
  9. Spark实践的阶段性总结
  10. 什么是IT行业? IT行业都有哪些职位?
  11. OSChina 十一乱弹 —— 前女友 is Null
  12. WBS(工作分解结构)
  13. 星星之火OIer:NOIP2018完爆总结
  14. 2019网易《Face-to-Parameter Translation for Game Character Auto-Creation》论文解析
  15. python如何根据数据画散点图_用python绘制散点图
  16. 机器人总动员cp图_阿尔法蛋冠名《人偶总动员4》 牵手高天鹤萌翻全场
  17. 2021年高考语文作文成绩查询,2021年国家高考语文作文题
  18. 又是好久不见的第五次
  19. ubuntu安装卸载cuda toolkit
  20. 《金钱永不眠》读后感及读书笔记

热门文章

  1. mysql 字符串索引 优化_MySQL性能优化之索引调优实战
  2. Nacos-快速入门
  3. 缓冲池Buffer Pool
  4. 序列化技术的选型-选型建议
  5. HttpCLient工具使用讲解
  6. HelloWorld程序的代码编写
  7. flume案例-网络数据采集-Flume的配置
  8. BufferedInputStream_字节缓冲输入流
  9. spring的依赖注入
  10. 编写Eureka入门案例