BZOJ2879 [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)。他想知道的是最小的总等待时间是多少。
输入格式
输入文件的第1行包含两个正整数n和m,表示菜品的种数和厨师的数量。 第2行包含n个正整数,其中第i个数为pi,表示点第i种菜品的人数。 接下来有n行,每行包含m个非负整数,这n行中的第i行的第j个数为ti,j,表示第j个厨师制作第i种菜品所需的时间。 输入文件中每行相邻的两个数之间均由一个空格隔开,行末均没有多余空格。
输出格式
输出仅一行包含一个整数,为总等待时间的最小值。
输入样例
3 2
3 1 1
5 7
3 6
8 9
输出样例
47
提示
【样例说明】
厨师1先制作1份菜品2,再制作2份菜品1。点这3道菜的3个同学的等待时间分别为3,3+5=8,3+5+5=13。
厨师2先制作1份菜品1,再制作1份菜品3。点这2道菜的2个同学的等待时间分别为7,7+9=16。
总等待时间为3+8+13+7+16=47。
虽然菜品1和菜品3由厨师1制作更快,如果这些菜品都由厨师1制作,总等待时间反而更长。如果按上述的做法,将1份菜品1和1份菜品3调整到厨师2制作,这样厨师2不会闲着,总等待时间更短。
可以证明,没有更优的点餐方案。
【数据规模及约定】
对于100%的数据,n <= 40, m <= 100, p <= 800, ti,j <= 1000(其中p = ∑pi,即点菜同学的总人数)。
每组数据的n、m和p值如下:
测试点编号 n m p
1 n = 5 m = 5 p = 10
2 n = 40 m = 1 p = 400
3 n = 40 m = 2 p = 300
4 n = 40 m = 40 p = 40
5 n = 5 m = 40 p = 100
6 n = 10 m = 50 p = 200
7 n = 20 m = 60 p = 400
8 n = 40 m = 80 p = 600
9 n = 40 m = 100 p = 800
10 n = 40 m = 100 p = 800
题解
和修车那题很像,就不具体说明了
但是因为点很多,要动态加边
当一个厨师完成了第k个任务时,再加入第k + 1条边
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define BUG(s,n) for (int i = 1; i <= (n); i++) cout<<s[i]<<' '; puts("");
using namespace std;
const int maxn = 100005,maxm = 3000005,INF = 1000000000;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 3) + (out << 1) + c - '0'; c = getchar();}
return out * flag;
}
int h[maxn],ne = 2,N,M,P,p[45],t[105][45],S,T;
struct EDGE{int from,to,nxt,f,w;}ed[maxm];
inline void build(int u,int v,int f,int w){
ed[ne] = (EDGE){u,v,h[u],f,w}; h[u] = ne++;
ed[ne] = (EDGE){v,u,h[v],0,-w}; h[v] = ne++;
}
queue<int> q;
bool inq[maxn];
int d[maxn],pre[maxn],minf[maxn],flow = 0,cost = 0;
bool spfa(){
for (int i = S; i <= T; i++) d[i] = INF;
int u; d[S] = 0; minf[S] = INF;
q.push(S);
while (!q.empty()){
u = q.front(); q.pop();
inq[u] = false;
Redge(u) if (ed[k].f && d[to = ed[k].to] > d[u] + ed[k].w){
d[to] = d[u] + ed[k].w; minf[to] = min(ed[k].f,minf[u]);
pre[to] = k;
if (!inq[to]) q.push(to),inq[to] = true;
}
}
return d[T] != INF;
}
void mcf(){
flow += minf[T]; cost += minf[T] * d[T]; int a,b;
for (int u = T; u != S; u = ed[pre[u]].from){
ed[pre[u]].f -= minf[T],ed[pre[u] ^ 1].f += minf[T];
if (ed[pre[u]].from == S)
a = (u - 1) / P + 1,b = u % P + 1;
}
REP(i,N) build((a - 1) * P + b,M * P + i,1,b * t[a][i]);
}
int main(){
//freopen("in.txt","r",stdin);
//freopen("out1.txt","w",stdout);
N = RD(); M = RD();
REP(i,N) P += (p[i] = RD());
REP(i,N) REP(j,M) t[j][i] = RD();
S = 0; T = M * P + N + 1;
REP(i,M * P) build(S,i,1,0);
REP(i,N) build(M * P + i,T,p[i],0);
REP(i,N) REP(j,M) build((j - 1) * P + 1,M * P + i,1,t[j][i]);
while (spfa()) mcf();
printf("%d",cost);
return 0;
}
BZOJ2879 [Noi2012]美食节 【费用流】的更多相关文章
- [BZOJ2879][NOI2012]美食节(费用流)
设sm为所有p之和,套路地对每道菜建一个点,将每个厨师拆成sm个点,做的倒数第i道菜的代价为time*i. S向每道菜连边<0,p[i]>(前者为代价后者为流量),i菜到j厨师的第k个点连 ...
- [BZOJ2879] [Noi2012] 美食节 (费用流 & 动态加边)
Description CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽 ...
- 【bzoj2879】[Noi2012]美食节 费用流+动态加边
原文地址:http://www.cnblogs.com/GXZlegend 题目描述 CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他 ...
- [NOI2012]美食节(费用流)
题目描述 CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽管所有的菜品都 ...
- [NOI2012]美食节——费用流(带权二分图匹配)+动态加边
题目描述 小M发现,美食节共有n种不同的菜品.每次点餐,每个同学可以选择其中的一个菜品.总共有m个厨师来制作这些菜品.当所有的同学点餐结束后,菜品的制作任务就会分配给每个厨师.然后每个厨师就会同时开始 ...
- BZOJ 2879: [Noi2012]美食节( 费用流 + 动态加边 )
倒着做菜..然后考虑为当前的人做菜对后面的人的影响就可以了..要动态加边 --------------------------------------------------------------- ...
- 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 ...
随机推荐
- 7-1 python 操作redis
1.安装并导入redis模块 # pip install redis 安装redis模块 import redis # 导入redis模块 2.连接一个或多个redis,指定数据库名,并指定返回字符串 ...
- ThinkPHP路由去掉隐藏URL中的index.php
官方默认的.htaccess文件 <IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews RewriteEngine On ...
- PHP提取奇数或偶数下标元素
该功能主要用到 array_filter() 函数,这个函数可以用回调函数过滤数组中的单元.用法: array array_filter ( array $array [, callable $cal ...
- 基于form表单submit提交不跳转
方法一:target <html> <body> <form action="" method="post" target=&qu ...
- vue.js实践应用
对于vue.js,不想多比比,直接搞上源码+图片 <!DOCTYPE html> <html> <head> <meta charset="utf- ...
- 数据结构学习-AVL平衡树
环境:C++ 11 + win10 IDE:Clion 2018.3 AVL平衡树是在BST二叉查找树的基础上添加了平衡机制. 我们把平衡的BST认为是任一节点的左子树和右子树的高度差为-1,0,1中 ...
- 笔记-python-lib-lxml
笔记-python-lib-lxml 1. lxml简介 lxml是一个实现解析网页文件的库,python中自带有解析库,但没有lxml方便好用. The lxml XML toolkit ...
- Python logging 模块简介
Table of Contents 1. Logging 模块 1.1. 简介 1.2. 简单输出日志 1.3. 输入日志到文件 1.4. 几个基本概念 1.4.1. loggers 1.4.2. h ...
- 6 Django的视图层
视图函数 一个视图函数,简称视图,是一个简单的Python 函数,它接受Web请求并且返回Web响应.响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. . ...
- 15.4,redis不重启,切换RDB备份到AOF备份
确保redis版本在2.2以上 [root@pyyuc /data ::]#redis-server -v Redis server v= sha=: malloc=jemalloc- bits= ...