题意

\(m\)个厨师,\(n\)种菜,每种菜需要做\(p_i\)份,每个厨师做第\(i\)种菜用时\(t_{i, j}\)。一个厨师做完一道菜才能做下一道。每份菜的时间是这个厨师做完这道菜的用时加上之前做过的菜的用时。问做完所有的菜的最小用时是多少。($ n \le 40, m \le 100, \sum p_i \le 800, t_{i, j} \le 1000 $)

分析

可以考虑每个厨师做的每一道菜。最后做的菜对时间贡献了一次,倒数第二的菜对时间贡献了两次。于是我们考虑每个厨师倒着做的菜品即可。

题解

将每个厨师拆成\(\sum p_i\)个点,表示这个菜是倒数第\(i\)次做的。但是这样一次性把图建出来会tle。所以我们要优化。

考虑到每个厨师倒数第一个菜一定在倒数第二个菜先做,所以我们按照这个顺序来建图即可,即增广一次建一次。

具体做法是:

首先加入\(m\)个点,表示每个厨师倒数第一次做的菜。源\(S\)向这些点连边,容量\(1\),费用为\(0\)。再加入\(n\)个点,表示菜类,每个点向汇连边,容量为\(p_i\),费用为\(0\)。然后在厨师的点集中向菜类点集连边,容量为\(1\),费用为\(t_{i, j}\)。

然后增广一条路径。此时找出被增广的厨师,再新建一个点,表示这个厨师第二次做的菜。源\(S\)向这个点连边,容量为\(1\),费用为\(0\)。然后向菜类连边,容量为\(1\),费用为\(2 t_{i, j}\)。依次类推。

#include <bits/stdc++.h>
using namespace std;
const int N=45, M=105, nN=N+M+1000, nE=N*(M+800)*8, oo=0x3f3f3f3f;
int ihead[nN], cnt=1;
struct E {
int next, from, to, cap, w;
}e[nE];
void add(int x, int y, int cap, int w) {
e[++cnt]=(E){ihead[x], x, y, cap, w}; ihead[x]=cnt;
e[++cnt]=(E){ihead[y], y, x, 0, -w}; ihead[y]=cnt;
}
bool spfa(int s, int t, int n, int &ans) {
static int d[nN], q[nN], p[nN], fr, ta;
static bool vis[nN];
memset(d, 0x3f, sizeof(int)*(n+1));
fr=ta=0;
d[s]=0;
q[ta++]=s;
while(fr!=ta) {
int x=q[fr++];
fr=fr==nN?0:fr;
vis[x]=0;
for(int i=ihead[x]; i; i=e[i].next) {
if(!e[i].cap) {
continue;
}
int y=e[i].to;
if(d[y]>d[x]+e[i].w) {
d[y]=d[x]+e[i].w;
p[y]=i;
if(!vis[y]) {
vis[y]=1;
q[ta++]=y;
ta=ta==nN?0:ta;
}
}
}
}
if(d[t]==oo) {
return 0;
}
for(int x=t; x!=s; x=e[p[x]].from) e[p[x]].cap--, e[p[x]^1].cap++;
ans+=d[t];
return 1;
}
int n, m, p[N], sum, pos[M], num[M], t[N][M], nu[N];
int main() {
int ans=0;
scanf("%d%d", &n, &m);
for(int i=1; i<=n; ++i) {
scanf("%d", &p[i]);
sum+=p[i];
}
int S=n+m+sum+1, T=S+1;
for(int i=1; i<=n; ++i) {
add(S, i, p[i], 0);
for(int j=1; j<=m; ++j) {
scanf("%d", &t[i][j]);
}
}
for(int j=1; j<=m; ++j) {
int id=n+j;
add(id, T, 1, 0);
num[j]=1;
pos[j]=cnt;
for(int i=1; i<=n; ++i) {
add(i, id, 1, t[i][j]);
}
}
int tot=n+m;
while(spfa(S, T, T, ans)) {
int j=0;
for(j=1; j<=m && !e[pos[j]].cap; ++j);
++num[j];
++tot;
add(tot, T, 1, 0);
pos[j]=cnt;
for(int i=1; i<=n; ++i) {
add(i, tot, 1, num[j]*t[i][j]);
}
}
printf("%d\n", ans);
return 0;
}

【BZOJ】2879: [Noi2012]美食节的更多相关文章

  1. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  2. BZOJ 2879: [Noi2012]美食节 最小费用流 动态添边

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 324  Solved: 179[Submit][Status] ...

  3. BZOJ 2879: [Noi2012]美食节( 费用流 + 动态加边 )

    倒着做菜..然后考虑为当前的人做菜对后面的人的影响就可以了..要动态加边 --------------------------------------------------------------- ...

  4. BZOJ 2879 NOI2012美食节

    链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2879 CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M ...

  5. BZOJ.2879.[NOI2012]美食节(费用流SPFA)

    题目链接 /* 同"修车":对于每个厨师拆成p个点表示p个时间点,每个人向m个厨师每个时间点连边 这样边数O(nmp)+网络流 ≈O(nm*p^2)(假设SPFA线性) = GG ...

  6. BZOJ 2879 [Noi2012]美食节 | 费用流 动态开点

    这道题就是"修车"的数据加强版--但是数据范围扩大了好多,应对方法是"动态开点". 首先先把"所有厨师做的倒数第一道菜"和所有菜连边,然后跑 ...

  7. 2879: [Noi2012]美食节 - BZOJ

    Description CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽 ...

  8. 2879: [Noi2012]美食节

    Description CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽 ...

  9. 2879. [NOI2012]美食节【费用流】

    Description CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽 ...

随机推荐

  1. Web框架本质

    Web框架本质 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env python #coding:utf- ...

  2. Spring中的jar包详解

    下面给大家说说spring众多jar包的特点吧,无论对于初学spring的新手,还是spring高手,这篇文章都会给大家带来知识上的收获,如果你已经十分熟悉本文内容就当做一次温故知新吧.spring. ...

  3. c中malloc的用法

    转自:http://blog.sina.com.cn/s/blog_966f8e8501010if7.html Malloc 向系统申请分配指定size个字节的内存空间.返回类型是 void* 类型. ...

  4. 轻松学习RSA加密算法原理

    转自:http://blog.csdn.net/sunmenggmail/article/details/11994013 http://blog.csdn.net/q376420785/articl ...

  5. myeclipse+tomcat 工程名改名的问题 ——————完美解决方案

    当建好的工程再重命名之后,发布和访问的时候都还是原来的名字,这个问题纠结了我很久,最好找到解决方法,这里分享一下,希望大家不要再受这种困惑.解决方法: 点击工程右键->properties-&g ...

  6. servlet、genericservlet、httpservlet之间的区别

    转自:http://blog.csdn.net/rat9912345/article/details/5161789 当编写一个servlet时,必须直接或间接实现servlet接口,最可能实现的方法 ...

  7. 第六篇:在SOUI中用九宫格拉伸方式显示一个图片资源

    SOUI的初学者刚开始可能难以搞清楚在SOUI中显示一个图片资源的流程,这里做一个简单的示范. 首先我们准备好一张图,以下图为例. 第一步,我们首先把这个图片文件复制到demo的uires目录下,新建 ...

  8. Codeforces Round #337 (Div. 2) D. Vika and Segments 线段树 矩阵面积并

    D. Vika and Segments     Vika has an infinite sheet of squared paper. Initially all squares are whit ...

  9. Arduino101学习笔记(五)—— 模拟IO

    1.配置IO管脚 //***************************************************************************************** ...

  10. Mac OS 您需要安装旧 Java SE 6 运行环境才能打开“XXX” 问题

    问题描述: 今天在Mac OS上安装一个app的时候提示 “您需要安装旧 Java SE 6 运行环境才能打开 XXX” ,在网上搜索了一下,有说要改app的info.plist文件的,将其中的JVM ...