【bzoj1061】[NOI2008]志愿者招募 线性规划与费用流
题目描述
输入
输出
样例输入
3 3
2 3 4
1 2 2
2 3 5
3 3 2
样例输出
14
题解
线性规划与费用流
“事实上任何最大流,最小费用流,上下界网络流都是在解决一个线性规划问题”(摘自 wyfcyx 大爷的ppt)
具体地,在一个网络流问题中,把边看作变量,把点看作限制条件,就会得到一个线性规划问题。
当然,由于网络流的特性,这类线性规划问题只能是:每个变量出现次数为且仅为2次,且1次系数为+1,1次系数为-1。
如果我们能够将这类特殊的线性规划问题转化为网络流问题,就可以圆满地解决原问题。
考虑本题,限制条件就是每天大的志愿者数大于等于规定数量,求 ∑费用*数量 的最小值。
这样可能不是很清楚,这里用样例举例子:
设$x_i$表示第i类志愿者的人数
限制条件:$\begin{cases}x_i\ge0\\x_1\ge2\\x_1+x_2\ge3\\x_2+x_3\ge4\end{cases}$,要最小化$2x_1+5x_2+2x_3$
我们把不等关系转化为相等关系,可以得到新的限制条件:$\begin{cases}x_i\ge0\\y_i\ge0\\x_1=2+y_1\\x_1+x_2=3+y_2\\x_2+x_3=4+y_3\end{cases}$
这样尽管多了几个变量,却把不等关系转化为容易处理的相等关系,易于建图。
但是这样依然不满足我们使用网络流解决线性规划问题的条件,因为变量出现次数不全为2,且系数不为+1和-1。
此时我们想到差分,把0=0分别放到限制条件中相等关系的最上端与最下端,然后上下进行差分并移项,可以得到:$\begin{cases}x_i\ge0\\y_i\ge0\\x_1-y_1-2=0\\x_2+y_1-y_2-1=0\\x_3-x_1+y_2-y_3-1=0\\-x_2-x_3+y_3+4=0\end{cases}$
这样就把限制条件“神奇”地转化为能够使用网络流解决的问题。为什么?因为用到了题目中的“志愿者工作时间是si天到ti天”,即一定是连续的。我们差分的本质是:$x_i$系数为+1时表示第i类志愿者刚开始工作,$x_i$系数为-1时表示第i类志愿者刚结束工作。所以一定是两个时间点。
我们再回过头来看这个线性规划问题。如何来使用网络流来解决它?这用到了网络流“流量守恒”的性质,即除S和T外,流入流量=流出流量。
我们把系数为+1看作要流出的流量,系数为-1看作要流入的流量,那么显然正负相等,符合条件。对于同一个变量的值是固定的,所以应从+1流向-1;对于常数项,系数为+1则从该点流向T,系数为-1则从S流向该点。
由于限制条件是与变量$x_i$有关的,所以在变量$x_i$对应的边上加上费用,然后跑费用流即可出解。
总结一下建图方法:把题目中的n天转化为n个等式,差分得到n+1个,代表图中的点;对于第i类志愿者,加边si->ti+1,容量为inf,费用为ci;加边j-1->j,容量为inf,费用为0,代表限制条件中的y。对于每天需要的志愿者数量$a_i(1\le i\le n+1)$,如果$a_i>a_{i-1}$,则加边S->i,容量为$a_i-a_{i-1}$,费用为0(因为差分后右面系数为正,移项后为负,代表流入);否咋加边i->T,容量为$a_{i-1}-a_i$,费用为0.
然后跑最小费用最大流出解。
说了这么多其实代码还是很简单的。
#include <cstdio>
#include <cstring>
#include <queue>
#define N 5000
#define M 100000
#define inf 0x3f3f3f3f
using namespace std;
queue<int> q;
int a[N] , head[N] , to[M] , val[M] , cost[M] , next[M] , cnt = 1 , s , t , dis[N] , from[N] , pre[N];
void add(int x , int y , int v , int c)
{
to[++cnt] = y , val[cnt] = v , cost[cnt] = c , next[cnt] = head[x] , head[x] = cnt;
to[++cnt] = x , val[cnt] = 0 , cost[cnt] = -c , next[cnt] = head[y] , head[y] = cnt;
}
bool spfa()
{
int x , i;
memset(from , -1 , sizeof(from));
memset(dis , 0x3f , sizeof(dis));
dis[s] = 0 , q.push(s);
while(!q.empty())
{
x = q.front() , q.pop();
for(i = head[x] ; i ; i = next[i])
if(val[i] && dis[to[i]] > dis[x] + cost[i])
dis[to[i]] = dis[x] + cost[i] , from[to[i]] = x , pre[to[i]] = i , q.push(to[i]);
}
return ~from[t];
}
int mincost()
{
int ans = 0 , i , k;
while(spfa())
{
k = inf;
for(i = t ; i != s ; i = from[i]) k = min(k , val[pre[i]]);
ans += k * dis[t];
for(i = t ; i != s ; i = from[i]) val[pre[i]] -= k , val[pre[i] ^ 1] += k;
}
return ans;
}
int main()
{
int n , m , i , x , y , z;
scanf("%d%d" , &n , &m) , s = 0 , t = n + 2;
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]) , add(i + 1 , i , inf , 0);
for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%d" , &x , &y , &z) , add(x , y + 1 , inf , z);
for(i = 1 ; i <= n + 1 ; i ++ )
{
if(a[i] - a[i - 1] > 0) add(s , i , a[i] - a[i - 1] , 0);
if(a[i] - a[i - 1] < 0) add(i , t , a[i - 1] - a[i] , 0);
}
printf("%d\n" , mincost());
return 0;
}
【bzoj1061】[NOI2008]志愿者招募 线性规划与费用流的更多相关文章
- BZOJ1061 NOI2008 志愿者招募 线性规划、费用流
传送门 一道思路很妙的线性规划网络流 设\(X_i\)表示第\(i\)天需要的人数,\(P_i\)表示第\(i\)种人雇佣的个数 那么我们可以列出一系列式子 比如说样例就可以列出三个式子: \(P_1 ...
- [BZOJ1061][Noi2008]志愿者招募 线性规划+费用流
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1061 根据题意列方程,然后用网络流解线性规划. 题解直接贴ByVoid的吧,太神了:htt ...
- BZOJ1061: [Noi2008]志愿者招募(线性规划)
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 5725 Solved: 3437[Submit][Status][Discuss] Descript ...
- 网络流解线性规划问题 BZOJ1061: [Noi2008]志愿者招募
线性规划定义: 在给定有限的资源和竞争约束情况下,很多问题都可以表述为最大化或最小化某个目标.如果可以把目标指定为某些变量的线性函数,而且如果可以将资源约束指定为这些变量的等式或不等式,则得到了一个线 ...
- [BZOJ1061][Noi2008]志愿者招募
[BZOJ1061][Noi2008]志愿者招募 试题描述 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难 题:为即将启动的奥运新项目招募一批短期志愿 ...
- 【费用流】BZOJ1061: [Noi2008]志愿者招募(这题超好)
1061: [Noi2008]志愿者招募 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 5291 Solved: 3173[Submit][Stat ...
- 线性规划费用流解法(Bzoj1061: [Noi2008]志愿者招募)
题面 传送门 Sol 线性规划费用流解法用与求解未知数为非负数的问题 这道题可以列出一堆形如 \(x[i]+x[j]+x[k]+...>=a[p]\) 的不等式 我们强行给每个式子减去一个东西, ...
- [BZOJ1061] [Noi2008] 志愿者招募 (费用流)
Description 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难 题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能 ...
- BZOJ.1061.[NOI2008]志愿者招募(线性规划 对偶原理 单纯形 / 费用流SPFA)
题目链接 线性规划 用\(A_{ij}=0/1\)表示第\(i\)天\(j\)类志愿者能否被招募,\(x_i\)为\(i\)类志愿者招募了多少人,\(need_i\)表示第\(i\)天需要多少人,\( ...
随机推荐
- Co. - Microsoft - Windows - 通过任务计划,备份本地MySQL,数据上传Linux备份服务器
需求 客户为Windows系统,安装MySQL,需要每日备份数据库到指定目录,并且上传到公司的备份服务器(Linux). 1.使用mysqldump备份MySQL数据库,使用FTP上传到阿里云Linu ...
- mysql导出数据库表名与字段信息
一.导出数据库表格信息 #mysql导出库的表格信息 SELECT A.TABLE_SCHEMA, A.TABLE_NAME, A.TABLE_ROWS, A.CREATE_TIME, A.TABLE ...
- QP之QEP原理
1.QP简介: 量子平台(Quantum Platform, 简称QP)是一个用于实时嵌入式系统的软件框架,QP是轻量级的.开源的.基于层次式状态机的.事件驱动的平台. QP包括事件处理器(QEP). ...
- 机器学习基础之knn的简单例子
knn算法是人工智能的基本算法,类似于语言中的"hello world!",python中的机器学习核心模块:Scikit-Learn Scikit-learn(sklearn)模 ...
- 素数环 南阳acm488(回溯法)
素数环 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 有一个整数n,把从1到n的数字无重复的排列成环,且使每相邻两个数(包括首尾)的和都为素数,称为素数环. 为了简 ...
- windows程序内部运行机制
Windows程序内部运行机制 2007-10-21 19:52 1010人阅读 评论(0) 收藏 举报 windowsvc++applicationcallbackwinapistructure W ...
- 006---hashlib模块
hashlib模块 HASH 一般翻译成散列,也可以叫哈希. 把任意长度的输入通过散列算法变换成固定的长度. 该转换是一种压缩映射 MD5 输入任意长度的信息,经过处理.输出为128位的信息(数字指纹 ...
- .NET CORE LOG
.NET CORE LOG 合格的应用程序不仅要求运行的高效和计算的准确,稳定及可靠性也要得到满足,同事,系统的可维护性也相当重要.谈及到可维护性,就必须涉及到系统运行状态的监控和异常的快速定位与跟踪 ...
- (数据科学学习手札03)Python与R在随机数生成上的异同
随机数的使用是很多算法的关键步骤,例如蒙特卡洛法.遗传算法中的轮盘赌法的过程,因此对于任意一种语言,掌握其各类型随机数生成的方法至关重要,Python与R在随机数底层生成上都依靠梅森旋转(twiste ...
- R语言绘图:ROC曲线图
使用pROC包绘制ROC曲线 #####***绘制ROC曲线***##### library("pROC") N <- dim(data2)[1] #数据长度 set.see ...