【费用流】BZOJ1061: [Noi2008]志愿者招募(这题超好)
1061: [Noi2008]志愿者招募
Time Limit: 20 Sec Memory Limit: 162 MB
Submit: 5291 Solved: 3173
[Submit][Status][Discuss]
Description
Input
Output
仅包含一个整数,表示你所设计的最优方案的总费用。
Sample Input
2 3 4
1 2 2
2 3 5
3 3 2
Sample Output
HINT
1 ≤ N ≤ 1000,1 ≤ M ≤ 10000,题目中其他所涉及的数据均 不超过2^31-1。
题解
这题dalao们要不就是用线性规划来把不定方程转化为一般方程建边跑费用流
但是有dalao提出了这样一种建边方法(我们用二元组(cap,val)表示边的流量和花费):
- 对于每一天向后一天连边(inf−ai,0)
- 对于每一种志愿者选择,从L到R+1建边(inf,cost[i])
- 从超级源向第一天连边(inf,0)
- 从最后一天+1向超级汇连边(inf,0)
但是为什么这样是对的呢?
原谅本蒟蒻看了许多dalao们的解释都看不懂。。。
于是我就自己YY了一下:
- 假设有一种免费志愿者,他的工作区间为(1,n)
- 我们每天都需要inf个志愿者,其中有至少a[i]个非免费志愿者,也就是最多有inf-a[i]个免费志愿者
- 所以我们对于每一天向它的下一天连边(inf-a[i],0)意味着这一天工作完下一天继续工作的免费志愿者最多为inf-a[i]个(因为中间不能临时增加免费志愿者)
- 然后对于每个非免费志愿者i的工作区间(l,r),我们从l向r+1连一条边(inf,c[i])表示我们这几天可以花费每人c[i]的代价让免费志愿者直接去往第r+1天,而剩下的部分由非免费志愿者补齐
- 建立超级源点向第一天连(inf,0)表示第一天可以有inf个免费志愿者
- 从第n+1天向超级汇点连(inf,0)表示最后每天都要有inf个志愿者
- 这样就可以把有下限无上限的问题转化成有上限无下限的问题
跑费用流
代码
//by 减维
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<bitset>
#include<set>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<ctime>
#include<algorithm>
#define ll long long
#define db double
#define inf 2147483647//1<<29
#define maxn 20005
#define eps 1e-8
using namespace std; inline int read()
{
int ret=;bool fla=;char ch=getchar();
while((ch<''||ch>'')&&ch!='-')ch=getchar();
if(ch=='-'){fla=;ch=getchar();}
while(ch>=''&&ch<=''){ret=ret*+ch-'';ch=getchar();}
return fla?-ret:ret;
} struct edge{
int to,ne,cap,val;
}e[maxn<<]; int n,m,s,t,ecnt=,a[maxn],head[maxn],dis[maxn];
bool pd[maxn],vis[maxn]; void add(int x,int y,int z,int k)
{
ecnt++;e[ecnt]=(edge){y,head[x],z,k};head[x]=ecnt;
ecnt++;e[ecnt]=(edge){x,head[y],,-k};head[y]=ecnt;
} bool bfs()
{
deque<int>q;q.push_back(t);
for(int i=s;i<=t;++i)dis[i]=inf;dis[t]=;
memset(pd,,sizeof pd);pd[t]=;
while(!q.empty())
{
int d=q.front();q.pop_front();
pd[d]=;
for(int i=head[d];i;i=e[i].ne)
{
int dd=e[i].to;
if(e[i^].cap&&dis[dd]>dis[d]-e[i].val)
{
dis[dd]=dis[d]-e[i].val;
if(!pd[dd]){
pd[dd]=;
if(q.empty()||dis[dd]>dis[q.front()]) q.push_back(dd);
else q.push_front(dd);
}
}
}
}
return dis[s]<inf;
} int dfs(int x,int cap)
{
vis[x]=;
if(x==t||!cap)return cap;
int tmp,ret=;
for(int i=head[x];i;i=e[i].ne)
{
int dd=e[i].to;
if(!vis[dd]&&e[i].cap&&dis[dd]==dis[x]-e[i].val)
{
tmp=dfs(dd,min(e[i].cap,cap));
cap-=tmp;ret+=tmp;
e[i].cap-=tmp;e[i^].cap+=tmp;
}
}
return ret;
} int zkw()
{
int ret=;
while(bfs())
{
vis[t]=;
while(vis[t]){
memset(vis,,sizeof vis);
ret+=dfs(s,inf)*dis[s];
}
}
return ret;
} int main()
{
n=read();m=read();
s=,t=n+;
for(int i=;i<=n;++i) a[i]=read(),add(i,i+,inf-a[i],);
for(int i=,x,l,r;i<=m;++i) l=read(),r=read(),x=read(),add(l,r+,inf,x);
add(s,,inf,);add(n+,t,inf,);
printf("%d",zkw());
return ;
}
【费用流】BZOJ1061: [Noi2008]志愿者招募(这题超好)的更多相关文章
- 【费用流】NOI2008志愿者招募
1061: [Noi2008]志愿者招募 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 5171 Solved: 3089[Submit][Stat ...
- [BZOJ1061][Noi2008]志愿者招募
[BZOJ1061][Noi2008]志愿者招募 试题描述 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难 题:为即将启动的奥运新项目招募一批短期志愿 ...
- 网络流解线性规划问题 BZOJ1061: [Noi2008]志愿者招募
线性规划定义: 在给定有限的资源和竞争约束情况下,很多问题都可以表述为最大化或最小化某个目标.如果可以把目标指定为某些变量的线性函数,而且如果可以将资源约束指定为这些变量的等式或不等式,则得到了一个线 ...
- [BZOJ1061] [Noi2008] 志愿者招募 (费用流)
Description 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难 题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能 ...
- 线性规划费用流解法(Bzoj1061: [Noi2008]志愿者招募)
题面 传送门 Sol 线性规划费用流解法用与求解未知数为非负数的问题 这道题可以列出一堆形如 \(x[i]+x[j]+x[k]+...>=a[p]\) 的不等式 我们强行给每个式子减去一个东西, ...
- BZOJ1061 [Noi2008]志愿者招募 【单纯形】
题目链接 BZOJ1061 题解 今天终于用正宗的线性规划\(A\)了这道题 题目可以看做有\(N\)个限制和\(M\)个变量 变量\(x_i\)表示第\(i\)种志愿者的人数,对于第\(i\)种志愿 ...
- 【费用流】BZOJ1061[NOI2008]-志愿者招募
[题目大意] 一个项目需要n天完成,其中第i天至少需要Ai个人.共有m类人可以招募,其中第i类可以从第Si天做到第Ti天,每人的招募费用为Ci元.求最小招募费用. [思路] byvoid神犇的建图详解 ...
- BZOJ1061 NOI2008 志愿者招募 线性规划、费用流
传送门 一道思路很妙的线性规划网络流 设\(X_i\)表示第\(i\)天需要的人数,\(P_i\)表示第\(i\)种人雇佣的个数 那么我们可以列出一系列式子 比如说样例就可以列出三个式子: \(P_1 ...
- [BZOJ1061][Noi2008]志愿者招募 线性规划+费用流
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1061 根据题意列方程,然后用网络流解线性规划. 题解直接贴ByVoid的吧,太神了:htt ...
随机推荐
- Ration Rose2003安装及破解
曾经学习UML的时候,用的是EA. 近期在看Head First想着画绘图装一下Ration Rose吧.于是就着手開始装.本来网上关于Ration Rose的安装及破解教程非常多,可是我在安装的过程 ...
- win7中用 httplistener 出现 503 错误的问题
项目中须要用httplistener提供一个简单的httpserver服务.可是执行都是提示: UnHandledException Message:拒绝訪问 在System.Net.HttpList ...
- JAVA入门[12]-JavaBean
一.什么是JavaBean JavaBean是特殊的Java类,使用Java语言书写,并且遵守规范: 提供一个默认的无参构造函数. 需要被序列化并且实现了Serializable接口. 可能有一系列可 ...
- mysql主从备份及常见问题处理
1.mysql主从备份基本原理 mysql支持单向.异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器.mysql复制基于主服务器在二进制日志中跟踪所有对数据库的更改(更新 ...
- 【quickhybrid】API规划
前言 当一切就绪后,就要开始进行API规划,这一块是整个Hybrid框架中非常重要的内容,毕竟对于前端页面来说,只会通过JS API来调用功能. 基本上,API调用起来是否方便简洁影响着整个体验. 这 ...
- 关于java以及JavaScript或者更多的语言中Data类的问题
关于java和JavaScript以及各类编程语言里Data类的月份问题,日子是从1开始数,但是星期和月份对应的周一和1月都不是1,这是为什么呢? 很多新手对此可能会不理解,老手觉得这没啥,但是我觉得 ...
- Java中进制的转换函数
十进制转成十六进制: Integer.toHexString(int i) 十进制转成八进制 Integer.toOctalString(int i) 十进制转成二进制 Integer.toBinar ...
- 学习Lua setmetatable Lua 元表
Lua 元表(Metatable) 在 Lua table 中我们可以访问对应的key来得到value值,但是却无法对两个 table 进行操作. 个人理解,这个相当于其他语言的继承,是把这个类的方法 ...
- Vue.js(一)了解Vue
什么是Vue? 1.Vue.js是一个构建数据驱动的web界面的库.类似于Angularjs,在技术上,他重点集中在MVVM模式的View层,非常容易学习,非常容易和其他的库或已有的项目整合. 2.V ...
- ArcGIS Runtime SDK是什么?
如上图,Runtime SDK是什么东西?居然还有安卓.苹果手机.Mac.QT的版本? 是不是意味着ArcGIS的编辑数据和空间分析可以通过编程的方法在每个平台上满地跑了? 答案是:是,也不是. 1. ...