[NOI2012]美食节(费用流)
题目描述
CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节。作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴。他很快就尝遍了美食节所有的美食。然而,尝鲜的欲望是难以满足的。尽管所有的菜品都很可口,厨师做菜的速度也很快,小M仍然觉得自己桌上没有已经摆在别人餐桌上的美食是一件无法忍受的事情。于是小M开始研究起了做菜顺序的问题,即安排一个做菜的顺序使得同学们的等待时间最短。小M发现,美食节共有n种不同的菜品。每次点餐,每个同学可以选择其中的一个菜品。总共有m个厨师来制作这些菜品。当所有的同学点餐结束后,菜品的制作任务就会分配给每个厨师。然后每个厨师就会同时开始做菜。厨师们会按照要求的顺序进行制作,并且每次只能制作一人份。此外,小M还发现了另一件有意思的事情: 虽然这m个厨师都会制作全部的n种菜品,但对于同一菜品,不同厨师的制作时间未必相同。他将菜品用1, 2, ..., n依次编号,厨师用1, 2, ..., m依次编号,将第j个厨师制作第i种菜品的时间记为 ti,j 。小M认为:每个同学的等待时间为所有厨师开始做菜起,到自己那份菜品完成为止的时间总长度。换句话说,如果一个同学点的菜是某个厨师做的第k道菜,则他的等待时间就是这个厨师制作前k道菜的时间之和。而总等待时间为所有同学的等待时间之和。现在,小M找到了所有同学的点菜信息: 有 pi 个同学点了第i种菜品(i=1, 2, ..., n)。他想知道的是最小的总等待时间是多少。
题解
一开始按照修车那题的思路搞了个费用流,就是把厨师拆成tim个点,表示他是倒数第几个做的,然后边权就是对后面的人的代价和,然后T到飞起。
原因是直接把图建出来导致图的规模过大,然后spfa就死了。
所以我们可以动态加边,每增广一次就加一个点。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define N 49
#define M 109
#define P 809
#define R register
using namespace std;
queue<int>q;
int p[N],head[M*P],tot=,dis[M*P],pre[M*P],fl[M*P],ans,n,m,sum,a[N][M],tim[M*P],id[M],be[M*P];
bool vis[M*P];
inline int rd(){
int x=;char c=getchar();bool f=;
while(!isdigit(c)){if(c=='-')f=;c=getchar();}
while(isdigit(c)){x=(x<<)+(x<<)+(c^);c=getchar();}
return f?-x:x;
}
struct edge{int n,to,l,f;}e[N*M*P*];
inline void add(int u,int v,int l,int f){
e[++tot].n=head[u];e[tot].to=v;head[u]=tot;e[tot].l=l;e[tot].f=f;
e[++tot].n=head[v];e[tot].to=u;head[v]=tot;e[tot].l=;e[tot].f=-f;
}
inline bool spfa(int s,int t){
memset(dis,0x3f,sizeof(dis));
q.push(s);dis[s]=;fl[s]=2e9;
while(!q.empty()){
int u=q.front();q.pop();vis[u]=;
// cout<<u<<" "<<dis[u]<<endl;
for(R int i=head[u];i;i=e[i].n){
int v=e[i].to;
if(e[i].l&&dis[v]>dis[u]+e[i].f){
dis[v]=dis[u]+e[i].f;pre[v]=i;fl[v]=min(fl[u],e[i].l);
if(!vis[v]){vis[v]=;q.push(v);}
}
}
}
return dis[t]!=0x3f3f3f3f;
}
inline void calc(int s,int t){
int x=t;
while(x!=s){
int i=pre[x];
e[i].l-=fl[t];e[i^].l+=fl[t];x=e[i^].to;
}
ans+=dis[t]*fl[t];
}
int main(){
n=rd();m=rd();
for(R int i=;i<=n;++i)p[i]=rd(),sum+=p[i];
for(R int i=;i<=n;++i)for(R int j=;j<=m;++j)a[i][j]=rd();
int now=n;
for(R int i=;i<=m;++i)for(R int j=;j<=sum;++j){
++now;tim[now]=j==?:tim[now-]+;if(j==)id[i]=now;be[now]=i;
}
for(R int i=;i<=n;++i)for(R int j=;j<=m;++j)add(i,id[j],,a[i][j]);
for(R int i=;i<=m;++i)add(id[i],now+,,);
for(R int i=;i<=n;++i)add(,i,p[i],);
while(spfa(,now+)){
calc(,now+);
int x=e[pre[now+]^].to;x++;
add(x,now+,,);
for(int i=;i<=n;++i)add(i,x,,tim[x]*a[i][be[x]]);
}
cout<<ans;
return ;
}
[NOI2012]美食节(费用流)的更多相关文章
- [NOI2012]美食节——费用流(带权二分图匹配)+动态加边
题目描述 小M发现,美食节共有n种不同的菜品.每次点餐,每个同学可以选择其中的一个菜品.总共有m个厨师来制作这些菜品.当所有的同学点餐结束后,菜品的制作任务就会分配给每个厨师.然后每个厨师就会同时开始 ...
- 【bzoj2879】[Noi2012]美食节 费用流+动态加边
原文地址:http://www.cnblogs.com/GXZlegend 题目描述 CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他 ...
- BZOJ 2879: [Noi2012]美食节( 费用流 + 动态加边 )
倒着做菜..然后考虑为当前的人做菜对后面的人的影响就可以了..要动态加边 --------------------------------------------------------------- ...
- [BZOJ2879][NOI2012]美食节(费用流)
设sm为所有p之和,套路地对每道菜建一个点,将每个厨师拆成sm个点,做的倒数第i道菜的代价为time*i. S向每道菜连边<0,p[i]>(前者为代价后者为流量),i菜到j厨师的第k个点连 ...
- [BZOJ2879] [Noi2012] 美食节 (费用流 & 动态加边)
Description CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽 ...
- BZOJ.2879.[NOI2012]美食节(费用流SPFA)
题目链接 /* 同"修车":对于每个厨师拆成p个点表示p个时间点,每个人向m个厨师每个时间点连边 这样边数O(nmp)+网络流 ≈O(nm*p^2)(假设SPFA线性) = GG ...
- 【BZOJ 2879】[Noi2012]美食节 费用流
思路同修车,就是多了一个骚气的操作:动态加边,我们通过spfa流的过程可以知道,我们一次只会跑一流量,最后一层边跑过就不会再悔改,所以说我们只会用到一大片里面的很少的点,所以我们如果可以动态加边的话我 ...
- BZOJ 2879 [Noi2012]美食节 | 费用流 动态开点
这道题就是"修车"的数据加强版--但是数据范围扩大了好多,应对方法是"动态开点". 首先先把"所有厨师做的倒数第一道菜"和所有菜连边,然后跑 ...
- [NOI2012][bzoj2879] 美食节 [费用流+动态加边]
题面 传送门 思路 先看看这道题 修车 仔细理解一下,这两道题是不是一样的? 这道题的不同之处 但是有一个区别:本题中每一种车有多个需求,但是这个好办,连边的时候容量涨成$p\lbrack i\rbr ...
随机推荐
- TortoiseGit push免输密码
(ฅ>ω<*ฅ) 噫又好了~ TortoiseGit push免输密码的方法 – 晨旭的博客~https://www.chenxublog.com/2016/03/04/tortoiseg ...
- How to Configure Email Notification in Jenkins
How to Configure Email Notification in Jenkins? - The Official 360logica Bloghttps://www.360logica.c ...
- react中如何使用动画效果
在react中想要加入动画效果 需要引入 import {CSSTransitionGroup} from 'react-transition-group' //加入react 动画包 import ...
- findBugs安装
点击“Help->InstallNew Software”,如下图所示: 2 接着如下图所示: 3 Name”输入“findBugs”,“Location”输入“http://findbugs. ...
- [转帖]SSH 的 三种代理功能.
https://www.zhihu.com/people/skywind3000/activities 之前用过frp 知道 ssh 有一 反向代理的功能 没想到 还有这么多高级功能 收藏一下. ss ...
- C# Note2:委托(delegate) & Lambda表达式 & 事件(event)
前言 本文主要讲述委托和Lambda表达式的基础知识,以及如何通过Lambda表达式实现委托调用,并阐述.NET如何将委托用作实现事件的方式. 参考:C#高级编程 1.什么是委托(delegate)? ...
- PDO连接mysql数据库加载慢
今天在使用PDO连接mysql操作数据库的时候,发现速度特别慢,都1~2s的时间,不知道怎么回事,后来一步一步排除到new PDO 导致过慢的原因, 这个尴尬了...,调试了半天都没想到问下度娘,才知 ...
- python学习笔记(9)--函数
函数定义: def <函数名>(<参数(0个或多个)>): 函数体 return <返回值> 参数有非可选参数,和可选参数,可选参数放在参数列表的最后,可以为可选参 ...
- kubernetes资源类别介绍
类别 名称 资源对象 Pod.ReplicaSet.ReplicationController.Deployment.StatefulSet.DaemonSet.Job.CronJob.Horizon ...
- 怎样利用ADO中的adoquery进行缓存更新?????(100分)
我用BDE时,用query与updatesql相结合进行缓存更新,但是在ADO中没有updatesql,只有用adoquery,在DBGRID中,用CANCELUPADTE,只能取消一条记录,烦恼不已 ...