BZOJ1061 NOI2008 志愿者招募 线性规划、费用流
一道思路很妙的线性规划网络流
设\(X_i\)表示第\(i\)天需要的人数,\(P_i\)表示第\(i\)种人雇佣的个数
那么我们可以列出一系列式子
比如说样例就可以列出三个式子:
\(P_1 \geq X_1=2\)
\(P_1 + P_2 \geq X_2 = 3\)
\(P_2 + P_3 \geq X_3=4\)
加入\(N\)个辅助变量\(Y_i\)将式子变为
\(P_1 = 2 + Y_1\)
\(P_1 + P_2 = 3 + Y_2\)
\(P_2+P_3 = 4 + Y_3\)
最后加一个\(0=0\)
然后从第二个式子开始,每一个式子减去上面的一个式子
\(P_1 = 2 + Y_1\)
\(P_2 = 1 + Y_2 - Y_1\)
\(P_3 - P_1 = 1 + Y_3 - Y_2\)
\(-P_2-P_3 = -4 - Y_3\)
稍加变换,把负号项移到另一边
\(P_1=2+Y_1\)
\(P_2 + Y_1 = 1 + Y_2\)
\(P_3 + Y_2 = 1 + Y_3 + P_1\)
\(4 + Y_3 = P_2 + P_3\)
可以发现对于每一个变量,都在这些式子中出现了两次,而且一次在左边,一次在右边(虽然可以将等式两边倒过来但这并不是重点)
我们将每一个式子看作一个点,等式左边看作这一个点的出度,等式右边看作这一个点的入度,也就是需要满足网络流中的流量平衡。而一个变量刚好能够对应网络流中的一条有向边,一个常量又可以看作是从源点或者汇点向其连接的一条有向边。
那么网络流的构图就比较清晰了:
我们对于所有式子建立一个点
式子中的常量对应的是\(X_i-X_{i-1}\),也就是说如果\(X_i - X_{i-1} > 0\)则从\(S\)向\(i\)连一条流量为\(X_i - X_{i-1}\),费用为\(0\)的边,反之从这个点连向\(T\),流量为\(X_{i-1}-X_i\),费用为\(0\)。
对于式子中的变量则会连在两个式子之间,这个就留给读者自行思考了(明明是不想写)
#include<bits/stdc++.h>
#define int long long
#define INF 0x3f3f3f3f
//This code is written by Itst
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
bool f = 0;
while(!isdigit(c) && c != EOF){
if(c == '-')
f = 1;
c = getchar();
}
if(c == EOF)
exit(0);
while(isdigit(c)){
a = (a << 3) + (a << 1) + (c ^ '0');
c = getchar();
}
return f ? -a : a;
}
const int MAXN = 1007 , MAXM = 100007;
struct Edge{
int end , upEd , f , c;
}Ed[MAXM];
int head[MAXN] , dis[MAXN] , pre[MAXN] , flo[MAXN];
int N , M , S , T , cntEd = 1;
bool vis[MAXN];
queue < int > q;
inline void addEd(int a , int b , int c , int d = 0){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
Ed[cntEd].f = c;
Ed[cntEd].c = d;
head[a] = cntEd;
}
inline bool SPFA(){
memset(dis , 0x3f , sizeof(dis));
dis[S] = 0;
while(!q.empty())
q.pop();
q.push(S);
flo[S] = INF;
while(!q.empty()){
int t = q.front();
q.pop();
vis[t] = 0;
for(int i = head[t] ; i ; i = Ed[i].upEd)
if(Ed[i].f && dis[Ed[i].end] > dis[t] + Ed[i].c){
dis[Ed[i].end] = dis[t] + Ed[i].c;
flo[Ed[i].end] = min(Ed[i].f , flo[t]);
pre[Ed[i].end] = i;
if(!vis[Ed[i].end]){
vis[Ed[i].end] = 1;
q.push(Ed[i].end);
}
}
}
return dis[T] != dis[T + 1];
}
int EK(){
int ans = 0;
while(SPFA()){
int cur = T , sum = 0;
while(cur != S){
sum += Ed[pre[cur]].c;
Ed[pre[cur]].f -= flo[T];
Ed[pre[cur] ^ 1].f += flo[T];
cur = Ed[pre[cur] ^ 1].end;
}
ans += sum * flo[T];
}
return ans;
}
signed main(){
#ifndef ONLINE_JUDGE
freopen("in" , "r" , stdin);
//freopen("out" , "w" , stdout);
#endif
N = read();
M = read();
T = N + 2;
int a = 0;
for(int i = 1 ; i <= N ; ++i){
int b = read();
if(b > a){
addEd(S , i , b - a);
addEd(i , S , 0);
}
else{
addEd(i , T , a - b);
addEd(T , i , 0);
}
a = b;
}
addEd(N + 1 , T , a);
addEd(T , N + 1 , 0);
for(int i = 2 ; i <= N + 1 ; ++i){
addEd(i , i - 1 , INF);
addEd(i - 1 , i , 0);
}
for(int i = 1 ; i <= M ; ++i){
int l = read() , r = read() , c = read();
addEd(l , r + 1 , INF , c);
addEd(r + 1 , l , 0 , -c);
}
cout << EK();
return 0;
}
BZOJ1061 NOI2008 志愿者招募 线性规划、费用流的更多相关文章
- [BZOJ1061][Noi2008]志愿者招募 线性规划+费用流
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1061 根据题意列方程,然后用网络流解线性规划. 题解直接贴ByVoid的吧,太神了:htt ...
- 【BZOJ】1061: [Noi2008]志愿者招募(费用流+数学)
http://www.lydsy.com/JudgeOnline/problem.php?id=1061 好神的一题! 学会了一种建模方式: 当方程组内的任意变量都在其中两个方程出现且一正一负,可以建 ...
- BZOJ 1061 [Noi2008]志愿者招募(费用流)
题目描述 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能完成,其中第i ...
- BZOJ1061: [Noi2008]志愿者招募(线性规划)
Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 5725 Solved: 3437[Submit][Status][Discuss] Descript ...
- NOI2008 志愿者招募 (费用流)
题面 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能完成,其中第i 天至 ...
- 网络流解线性规划问题 BZOJ1061: [Noi2008]志愿者招募
线性规划定义: 在给定有限的资源和竞争约束情况下,很多问题都可以表述为最大化或最小化某个目标.如果可以把目标指定为某些变量的线性函数,而且如果可以将资源约束指定为这些变量的等式或不等式,则得到了一个线 ...
- [BZOJ1061][Noi2008]志愿者招募
[BZOJ1061][Noi2008]志愿者招募 试题描述 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难 题:为即将启动的奥运新项目招募一批短期志愿 ...
- 线性规划费用流解法(Bzoj1061: [Noi2008]志愿者招募)
题面 传送门 Sol 线性规划费用流解法用与求解未知数为非负数的问题 这道题可以列出一堆形如 \(x[i]+x[j]+x[k]+...>=a[p]\) 的不等式 我们强行给每个式子减去一个东西, ...
- 【费用流】BZOJ1061: [Noi2008]志愿者招募(这题超好)
1061: [Noi2008]志愿者招募 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 5291 Solved: 3173[Submit][Stat ...
随机推荐
- VS code 配置为 Python R LaTeX IDE
VS code配置为Python R LaTeX IDE VS code的中文断行.编辑功能强大,配置简单. VSC的扩展在应用商店搜索安装,快捷键ctrl+shift+x调出应用商店. 安装扩展后, ...
- Linux-pthread如何设置线程的优先级
设置线程优先级的函数: int pthread_setschedparam(pthread_t target_thread, int policy, const struct sched_param ...
- 生成器(generator,yield),next,send
#生成器 def generator(): for i in range(200): yield '哇哈哈%s' %i g = generator() #调用生成数函数,接受作用 ret = g.__ ...
- C#-多态(十二)
继承概念 多态:即一个接口,多个功能 同一种操作作用于不同的对象,可以有不同的解释,产生不同的执行结果 多态性可以是静态的或动态的.在静态多态性中,函数的响应是在编译时发生的.在动态多态性中,函数的响 ...
- web前端(6)—— 标签的属性,分类,嵌套
属性 HTML标签可以设置属性,属性一般以键值对的方式写在开始标签中 1.HTML标签除一些特定属性外可以设置自定义属性,一个标签可以设置多个属性用空格分隔,多个属性不区分先后顺序. 2.属性值要用引 ...
- 【audio】耳机插拔 线控按键识别流程【转】
耳机插拔/线控按键识别流程 耳机插拔/线控按键识别流程 1.文档概述 本文以msm8909平台,android N为例,介绍了通用情况下,耳机插拔的流程步骤,以及对耳机类型的识别逻辑.以方便在项目工作 ...
- perl语言中的.pm文件和.pl文件区别
perl...呵呵呵 按照惯例,.pm 应该保存 Perl Module,也就是 Perl 模块.例如 Socket.pm.pl 应该保存 Perl Library,也就是 Perl 库文件.例如 p ...
- Git&GitHub
Git是一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本管理. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软 ...
- nginx 拦截 swagger 登录
随着微服务的也来越多,每个服务都有单独的文档,那么问题来了,怎么把所有文档整合在一起呢 本方法采用服务器拦截的方式进行处理 首先需要在opt 的主目录中 /opt/ 创建一个新文件 htpasswd此 ...
- [福大软工] Z班 第2次成绩排行榜
作业链接 http://www.cnblogs.com/easteast/p/7469291.html 评分细则 本次个人项目分数由三部分组成,分别是 (1)博客 - 20分,分数组成如下: 在文章开 ...