BZOJ 1061 志愿者招募(最小费用最大流)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1061
题意:申奥成功后,布布经过不懈努力,终于 成为奥组委下属公司人力资源部门的主管。布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者。经过估算,这个项目需要N 天才能完成,其中第i 天至少需要Ai 个人。 布布通过了解得知,一共有M 类志愿者可以招募。其中第i 类可以从第Si 天工作到第Ti 天,招募费用是每人Ci 元。新官上任三把火,为了出色地完成自己的工作,布布希望用尽量少的费用招募足够的志愿者,但这并不是他的特长!于是布布找到了你,希望你帮他设计一种最 优的招募方案。
思路:
例如一共需要4天,四天需要的人数依次是4,2,5,3。有5类志愿者,如下表所示:
设雇佣第i类志愿者的人数为X[i],每个志愿者的费用为V[i],第j天雇佣的人数为P[j],则每天的雇佣人数应满足一个不等式,如上表所述,可以列出
P[1]=X[1]+X[2]>=4
P[2]=X[1]+X[3]>=2
P[3]=X[3]+X[4]+X[5]>=5
P[4]=X[5]>=3
对于第i个不等式,添加辅助变量Y[i](Y[i]>=0),可以使其变为等式
P[1]=X[1]+X[2]-Y[1]=4
P[2]=X[1]+X[3]-Y[2]=2
P[3]=X[3]+X[4]+X[5]-Y[3]=5
P[4]=X[5]-Y[4]=3
在上述四个等式上下添加P[0]=0,P[5]=0,每次用下边的式子减去上边的式子,得出
① P[1]-P[0]=X[1]+X[2]-Y[1]=4
② P[2]-P[1]=X[3]-X[2]-Y[2]+Y[1]=-2
③ P[3]-P[2]=X[4]+X[5]-X[1]-Y[3]+Y[2]=3
④ P[4]-P[3]=-X[3]-X[4]+Y[3]-Y[4]=-2
⑤ P[5]-P[4]=-X[5]+Y[4]=-3
观察发现,每个变量都在两个式子中出现了,而且一次为正,一次为负.所有等式右边和为0.我们将最后的五个等式进一步变形,得出以下结果
① -X[1]-X[2]+Y[1]+4=0
② -X[3]+X[2]+Y[2]-Y[1]-2=0
③ -X[4]-X[5]+X[1]+Y[3]-Y[2]+3=0
④ X[3]+X[4]-Y[3]+Y[4]-2=0
⑤ X[5]-Y[4]-3=0
可
以发现,每个等式左边都是几个变量和一个常数相加减,右边都为0,恰好就像网络流中除了源点和汇点的顶点都满足流量平衡。每个正的变量相当于流入该顶点的
流量,负的变量相当于流出该顶点的流量,而正常数可以看作来自附加源点的流量,负的常数是流向附加汇点的流量。因此可以据此构造网络,求出从附加源到附加
汇的网络最大流,即可满足所有等式。而我们还要求费用最小,所以要在X变量相对应的边上加上权值,然后求最小费用最大流。
接下来,根据上面五个等式构图。
(1)每个等式为图中一个顶点,添加源点S和汇点T。
(2)如果一个等式中的数字为非负整数c,从源点S向该等式对应的顶点连接一条容量为c,权值为0的有向边;如果为负整数-c,从该等式对应的顶点向汇点T连接一条容量为c,权值为0的有向边。
(3)如果一个变量X[i]在第j个等式中出现为-X[i],在第k个等式中出现为+X[i],从顶点j向顶点k连接一条容量为INF,权值为V[i]的有向边。
(4)如果一个变量Y[i]在第j个等式中出现为-Y[i],在第k个等式中出现为+Y[i],从顶点j向顶点k连接一条容量为INF,权值为0的有向边。
构图以后,求从源点S到汇点T的最小费用最大流,费用值就是结果。
struct node
{
int cost,flow,v,u,next;
}; node edges[N*1000];
int head[N],e,s,t;
int pre[N]; void add(int u,int v,int flow,int cost)
{
edges[e].u=u;
edges[e].v=v;
edges[e].cost=cost;
edges[e].flow=flow;
edges[e].next=head[u];
head[u]=e++;
} void Add(int u,int v,int flow,int cost)
{
add(u,v,flow,cost);
add(v,u,0,-cost);
} int SPFA(int s,int t)
{
clr(pre,-1);
int F[N],h[N],C[N],i,u,v,f,c;
queue<int> Q;
FOR0(i,t+1) C[i]=INF,h[i]=0,F[i]=0;
Q.push(s); C[s]=0; F[s]=INF;
while(!Q.empty())
{
u=Q.front();
Q.pop(); h[u]=0;
for(i=head[u];i!=-1;i=edges[i].next)
{
v=edges[i].v;
f=edges[i].flow;
c=edges[i].cost;
if(f>0&&C[v]>C[u]+c)
{
C[v]=C[u]+c;
F[v]=min(F[u],f);
pre[v]=i;
if(!h[v]) h[v]=1,Q.push(v);
}
}
}
return F[t];
} int MCMF(int s,int t)
{
int ans=0,i,temp;
while(temp=SPFA(s,t))
{
for(i=pre[t];i!=-1;i=pre[edges[i].u])
{
ans+=temp*edges[i].cost;
edges[i].flow-=temp;
edges[i^1].flow+=temp;
}
}
return ans;
} int n,m,d[N]; int main()
{
RD(n,m); clr(head,-1); e=0; s=0; t=n+2;
int i,u,v,c,temp;
FOR1(i,n) RD(d[i]);
FOR1(i,m)
{
RD(u,v,c);
Add(u,v+1,INF,c);
}
FOR1(i,n+1)
{
temp=d[i]-d[i-1];
if(temp>=0) Add(s,i,temp,0);
else Add(i,t,-temp,0);
if(i>1) Add(i,i-1,INF,0);
}
PR(MCMF(s,t));
}
BZOJ 1061 志愿者招募(最小费用最大流)的更多相关文章
- bzoj 1061 志愿者招募(最小费用最大流)
[Noi2008]志愿者招募 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 3792 Solved: 2314[Submit][Status][Di ...
- bzoj 1061 志愿者招募 有上下界费用流做法
把每一天看作一个点,每一天的志愿者数目就是流量限制,从i到i+1连边,上下界就是(A[i],+inf). 对于每一类志愿者,从T[i]+1到S[i]连边,费用为招募一个志愿者的费用,流量为inf.这样 ...
- BZOJ 1061 志愿者招募 最小费用流&&线性规划建模
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=1061 题目大意: 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主 ...
- BZOJ 1927 星际竞速(最小费用最大流)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1927 题意:一个图,n个点.对于给出的每条边 u,v,w,表示u和v中编号小的那个到编号 ...
- BZOJ 2424: [HAOI2010]订货(最小费用最大流)
最小费用最大流..乱搞即可 ------------------------------------------------------------------------------ #includ ...
- bzoj 1061 志愿者招募 费用流
详见BYV的博客,写的非常全面https://www.byvoid.com/blog/noi-2008-employee /************************************** ...
- BZOJ.3265.志愿者招募加强版(费用流SPFA)
题目链接 见上题. 每类志愿者可能是若干段,不满足那个...全幺模矩阵(全单位模矩阵)的条件,所以线性规划可能存在非整数解. 于是就可以用费用流水过去顺便拿个rank2 233. //20704kb ...
- BZOJ 1070: [SCOI2007]修车 [最小费用最大流]
1070: [SCOI2007]修车 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 4936 Solved: 2032[Submit][Status] ...
- BZOJ 1061 志愿者招募
http://www.lydsy.com/JudgeOnline/problem.php?id=1061 思路:可以用不等式的改装变成费用流. 将不等式列出,如果有负的常数,那么就从等式连向T,如果是 ...
随机推荐
- Install the 64bit library in Ubuntu13.10
After installed Ubuntu13.10, and i want to run a 32bit software, in the pass, you just run sudo apt- ...
- php常见细节错误
PHP编程中10个最常见的错误 PHP是一种非常流行的开源服务器端脚本语言,你在万维网看到的大多数网站都是使用php开发的.本篇经将为大家介绍PHP开发中10个最常见的问题,希望能够对朋友有所帮助. ...
- AndroidUI自动化测试工具-UIautomator
转自:http://www.cnblogs.com/rexmzk/archive/2012/12/26/2834380.html 最近公司在开展Android的自动化测试,美国那边的开发人员利用And ...
- [置顶] lua 进阶3--lua文件中调用C++函数
前面讲了一下,C++读取lua文件中的变量,包括一维表.二维表这些,这节讲一下如何在lua文件中去调用C++函数 C++代码如下 #include <stdio.h> extern &qu ...
- 在TVideoGrabber中如何在预览时设置相机属性
在使用TVideoGrabber进行预览时,如何设置相机的属性呢?比如曝光.对比度.亮度等. 下面来看一下,如何通过编程来调整这些设置: ——通过指定VideoDevice属性(在VideoDevic ...
- android 项目学习随笔七(ViewPagerIndicator与ViewPager)
1.ViewPagerIndicator https://github.com/JakeWharton/ViewPagerIndicator package com.viewpagerindicato ...
- laravel事务小例子
发生异常则自动回滚,正常则自动提交,示例如下: DB::connection('vshare')->transaction(function() use($id,$reason,$refuser ...
- REDHAT4.8安装yum
公司用的机器还在跑RHEL4(Red Hat Enterprise Linux AS 4.8),没有yum安装软件真是费时间啊,于是上网找了半天yum安装方法,终于成功.分享一下:核心:wget ht ...
- Pascal's Triangle II
class Solution { public: vector<int> getRow(int rowIndex) { vector<int> v; ) return v; v ...
- 两个升序链表的合并 Merge Two Sorted Lists 【 leetcode】
class Solution {public: ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { ListNode *p; ListN ...