题目链接

线性规划

  用\(A_{ij}=0/1\)表示第\(i\)天\(j\)类志愿者能否被招募,\(x_i\)为\(i\)类志愿者招募了多少人,\(need_i\)表示第\(i\)天需要多少人,\(C_i\)表示\(i\)类招募志愿者的花费。

  那么我们需要$$最小化\ Cx\s.t.\ Ax\geq need\x\geq 0$$

  (s.t.:subject to,使得满足)

  这是一个最小化线性规划,而不是标准型的最大化线性规划。根据对偶原理(见这儿),我们把它变成:$$最大化\ x*need\s.t.\ xA\leq C\x\geq 0$$

  用非矩阵形式直观地写:$$最小化\ \sum_{i=1}mC_ix_i\s.t. \sum_{i=1}nA_{ij}x_j\geq need_i\ ,\ j=1,2,\ldots,m\x_j\geq 0$$

  利用对偶原理,转化为:$$最大化\ \sum_{i=1}nneed_ix_i\s.t. \sum_{i=1}nA_{ij}x_i\leq C_j\ ,\ j=1,2,\ldots,m\x_i\geq 0$$

  这样就可以直接用单纯形做了。因为\(C_i\)非负,所以一定有解,不需要Init()。

  还有一个问题,线性规划的解是否可能非整数?

  我不知道为什么有这么个...常识定理?

线性规划的问题的最优解为整数的一个必要条件是它的任意一个子方阵的行列式为\(-1, 0, 1\)。

  反正这有\(Candy?\)的结论,我就记住吧。。

  下面有洛谷上题解的证明,证明本题方阵的任意一个子方阵的行列式为\(-1, 0或1\)。(全单位模矩阵

  另外加强版,单纯形应该不对,然而数据比较水。



Proof:


//79668kb	1172ms(果然还是比费用流慢多了)
#include <cmath>
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define eps 1e-8
const int N=1005,M=10005; int n,m;
double A[M][N];
char IN[MAXIN],*SS=IN,*TT=IN; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
void Pivot(int r,int c)
{
double t=A[r][c]; A[r][c]=1;
for(int i=0; i<=n; ++i) A[r][i]/=t;
for(int i=0; i<=m; ++i)
if(i!=r && fabs(A[i][c])>eps)
{
double t=A[i][c]; A[i][c]=0;
for(int j=0; j<=n; ++j) A[i][j]-=t*A[r][j];
}
}
void Simplex()
{
for(int r,c; ; )
{
r=c=0;
for(int i=1; i<=n; ++i)
if(A[0][i]>eps) {c=i; break;}
if(!c) break;
double mn=1e15;
for(int i=1; i<=m; ++i)
if(A[i][c]>eps && mn>A[i][0]/A[i][c]) r=i, mn=A[i][0]/A[i][c];
if(!r) break;
Pivot(r,c);
}
} int main()
{
n=read(), m=read();
for(int i=1; i<=n; ++i) A[0][i]=read();
for(int i=1,l,r; i<=m; ++i)
{
l=read(), r=read(), A[i][0]=read();
for(int j=l; j<=r; ++j) A[i][j]=1;
}
Simplex(), printf("%.0lf\n",-A[0][0]); return 0;
}

费用流

  用\(u\rightarrow v\ (f,\ c)\)表示一条\(u\rightarrow v\)容量为\(f\),花费为\(c\)的边。

  对于每一类志愿者,连边\(l_i\rightarrow r_i+1\ (INF,\ cost_i)\);

  每相邻的两天,连边\(i\rightarrow i+1\ (INF-need_i,\ 0)\);

  对于源点汇点,连边\(S\rightarrow 1\ (INF,\ 0)\)、\(n+1\rightarrow T\ (INF,\ 0)\)。

  因为一定存在可行解,所以最后流量一定可以扩充成INF。

  对于每两天之间的连边会优先流,因为花费为0,而不经过这条边但覆盖这一段的边的流量之和一定不小于\(need_i\)。即缺少的流量会通过带权边补成INF,且能保证方案最优。

  嗯...好吧我不会写费用流了。。


//1592kb	164ms
#include <queue>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=1007,M=11007<<1,INF=0x3f3f3f3f; int src,des,n,m,Enum,H[N],nxt[M],fr[M],to[M],cap[M],cost[M],pre[N],dis[N];
char IN[MAXIN],*SS=IN,*TT=IN; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AddEdge(int u,int v,int w,int c)
{
fr[++Enum]=u, to[Enum]=v, nxt[Enum]=H[u], H[u]=Enum, cap[Enum]=w, cost[Enum]=c;
fr[++Enum]=v, to[Enum]=u, nxt[Enum]=H[v], H[v]=Enum, cap[Enum]=0, cost[Enum]=-c;
}
bool SPFA()
{
static std::queue<int> q;
static bool inq[N];
memset(dis,0x3f,sizeof dis);
dis[src]=0, q.push(src);
while(!q.empty())
{
int x=q.front(); q.pop();
inq[x]=0;
for(int v,i=H[x]; i; i=nxt[i])
if(cap[i] && dis[v=to[i]]>dis[x]+cost[i])
{
dis[v]=dis[x]+cost[i], pre[v]=i;
if(!inq[v]) inq[v]=1, q.push(v);
}
}
return dis[des]<INF;
}
int MCMF()
{
int res=0, mn=INF;
for(int i=des; i!=src; i=fr[pre[i]])
mn=std::min(mn,cap[pre[i]]);
for(int i=des,v=pre[i]; i!=src; i=fr[v],v=pre[i])
res+=mn*cost[v], cap[v]-=mn, cap[v^1]+=mn;
return res;
} int main()
{
n=read(), m=read(), Enum=1, src=1, des=n+2;
for(int i=1; i<=n; ++i) AddEdge(i,i+1,INF-read(),0);
for(int i=1,l,r; i<=m; ++i) l=read(),r=read(),AddEdge(l,r+1,INF,read());
AddEdge(n+1,des,INF,0);
int res=0;
while(SPFA()) res+=MCMF();
printf("%d\n",res); return 0;
}

BZOJ.1061.[NOI2008]志愿者招募(线性规划 对偶原理 单纯形 / 费用流SPFA)的更多相关文章

  1. BZOJ 1061: [Noi2008]志愿者招募【单纯形裸题】

    1061: [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 4813  Solved: 2877[Submit][Stat ...

  2. BZOJ 1061: [Noi2008]志愿者招募 [单纯形法]【学习笔记】

    1061: [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3975  Solved: 2421[Submit][Stat ...

  3. BZOJ 1061: [Noi2008]志愿者招募 [单纯形法]【学习笔记看另一篇吧】

    1061: [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 3975  Solved: 2421[Submit][Stat ...

  4. BZOJ 1061: [Noi2008]志愿者招募

    1061: [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 4064  Solved: 2476[Submit][Stat ...

  5. BZOJ 1061: [Noi2008]志愿者招募 费用流

    1061: [Noi2008]志愿者招募 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1061 Description 申奥成功后,布布 ...

  6. 【刷题】BZOJ 1061 [Noi2008]志愿者招募

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

  7. BZOJ 1061: [Noi2008]志愿者招募(线性规划与网络流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1061 题意: 思路: 直接放上大神的建模过程!!!(https://www.byvoid.com/z ...

  8. BZOJ 1061 [Noi2008]志愿者招募(费用流)

    题目描述 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能完成,其中第i ...

  9. bzoj 1061 [Noi2008]志愿者招募(数学模型,MCMF)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1061 [题意] 雇人满足每天至少需要的人数. [思路一] Byvoid的题解 clic ...

随机推荐

  1. CF876 F 思维 枚举

    给你n个数,问有几个区间满足,区间内或操作大于区间内的任意数. 首先可以知道,两数或操作的结果必定不会小于两者间的最大值,也就是说对于一个区间中,不合法的状态只有两值或相等.那么我们可以考虑枚举每个数 ...

  2. js 正则学习小记之匹配字符串字面量

    今天看了第5章几个例子,有点收获,记录下来当作回顾也当作分享. 关于匹配字符串问题,有很多种类型,今天讨论 js 代码里的字符串匹配.(因为我想学完之后写个语法高亮练手,所以用js代码当作例子) va ...

  3. 《Linux命令行与shell脚本编程大全》23章24章

    第二十三章 使用其他shell bash shell是linux发行版中最广泛使用的shell.但是它并不是唯一的选择,还有其他的shell可以供你选择. 23.1 什么是dash shell 百度百 ...

  4. 40个新鲜的 jQuery 插件,使您的网站用户友好

    作为最流行的 JavaScript 开发框架,jQuery 在现在的 Web 开发项目中扮演着重要角色,它简化了 HTML 文档遍历,事件处理,动画以及 Ajax 交互,这篇文章特别收集了40个新鲜的 ...

  5. 一组数字,从1到n,从中减少了3个数,顺序打乱,放在n-3的数组里,找出丢失数字

    曾经看到有这样一个JS题:有一组数字,从1到n,从中减少了3个数,顺序也被打乱,放在一个n-3的数组里请找出丢失的数字,最好能有程序,最好算法比较快假设n=10000 下面我也来贴一个算法. func ...

  6. Burp-Suit之Interder

    登陆页面:http://localhost/pentest/brute/login.php 设置代理,使用Burp截断: 发送到Intruder进行爆破,这里我先说明一下Intruder页面 Inte ...

  7. String类的深入理解

    String不是基本数据类型,String和8种包装类型是不可变类.String和8种基本数据类型采用值传递. 关于方法区中的常量区和class文件中的常量区的关系,参考:https://www.cn ...

  8. linux笔记_day12_shell编程

    1.shell中如何进行算术运算 A=1 B=2 1)let 算术运算表达式 let C=$A+$B 2)$[算术运算表达式] C=$[$A+$B] 3)$(($A+$B)) 4) expr 算术表达 ...

  9. Linux TTY驱动--Serial Core层【转】

    转自:http://blog.csdn.net/sharecode/article/details/9197567 版权声明:本文为博主原创文章,未经博主允许不得转载. 接上一节: Linux TTY ...

  10. MAC连接安卓手机通过adb指令安装apk

    Android的apk可以通过adb命令来安装.在MAC电脑上,如果想通过命令行的方式给安卓手机安装apk,需要做以下操作: 一句话概括就是:将安卓SDK的adb命令添加到环境变量中,然后通过adb ...