BZOJ 2879 NOI2012美食节

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2879

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 #include<algorithm>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<iostream>
 6 #define N 200005
 7 int tot,go[3000005],first[200005],next[3000005],flow[3000005],cost[3000005];
 8 int op[3000005],from[N],edge[N],dis[N],vis[N],c[2*N];
 9 int a[505][505],n,m,p[N],ans,S,T,all;
10 int read(){
11     int t=0,f=1;char ch=getchar();
12     while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘) f=-1;ch=getchar();}
13     while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();}
14     return t*f;
15 }
16 void insert(int x,int y,int z,int l){
17     tot++;go[tot]=y;next[tot]=first[x];first[x]=tot;flow[tot]=z;cost[tot]=l;
18 }
19 void add(int x,int y,int z,int l){
20     insert(x,y,z,l);op[tot]=tot+1;insert(y,x,0,-l);op[tot]=tot-1;
21 }
22 bool spfa(){
23     for (int i=0;i<=T;i++) dis[i]=0x3f3f3f3f,vis[i]=0;
24     int h=1,t=1;dis[S]=0;c[1]=S;
25     while (h<=t){
26         int now=c[h++];
27         for (int i=first[now];i;i=next[i]){
28             int pur=go[i];
29             if (flow[i]&&dis[pur]>dis[now]+cost[i]){
30                 dis[pur]=dis[now]+cost[i];
31                 from[pur]=now;
32                 edge[pur]=i;
33                 if (vis[pur]) continue;
34                 vis[pur]=1;
35                 c[++t]=pur;
36             }
37         }
38         vis[now]=0;
39     }
40     return dis[T]!=0x3f3f3f3f;
41 }
42 void updata(){
43     int mn=0x7fffffff,x,y;
44     for (int i=T;i!=S;i=from[i]){
45         mn=std::min(mn,flow[edge[i]]);
46         if (from[i]==S){
47             x=(i-1)/all+1;
48             y=(i)%all+1;
49         }
50     }
51     for (int i=T;i!=S;i=from[i]){
52         ans+=mn*cost[edge[i]];
53         flow[edge[i]]-=mn;
54         flow[op[edge[i]]]+=mn;
55     }
56     for (int i=1;i<=m;i++)
57      add((x-1)*all+y,n*all+i,1,y*a[i][x]);
58 }
59 int main(){
60     m=read();n=read();
61     S=0;
62     for (int i=1;i<=m;i++){
63         p[i]=read();
64         all+=p[i];
65     }
66     T=m+n*all+1;
67     for (int i=1;i<=n*all;i++)
68      add(S,i,1,0);
69     for (int i=1;i<=m;i++)
70      add(i+n*all,T,p[i],0);
71     for (int i=1;i<=m;i++)
72      for (int j=1;j<=n;j++)
73       a[i][j]=read();
74     for (int i=1;i<=n;i++)
75      for (int j=1;j<=m;j++)
76       add((i-1)*all+1,n*all+j,1,a[j][i]);
77     while (spfa()) updata();
78     printf("%d\n",ans);
79 }
时间: 2024-12-29 11:33:57

BZOJ 2879 NOI2012美食节的相关文章

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

2879: [Noi2012]美食节 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 1453 Solved: 778 [Submit][Status][Discuss] Description CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的... http://bbs.chinaacc.com/forum-2-3/topic-5785721.html ht

BZOJ 2879 NOI2012 美食节 费用流

题目大意:给定n道菜和m个厨师,第i道菜需要p[i]份,第j个厨师做第i道菜需要时间t[i][j],求最长总等待时间 一个厨师做的倒数第一道菜对答案的贡献是时间的一倍,倒数第二道菜对答案的贡献是时间的两倍,以此类推 厨师们怒了!发动符卡·禁忌『p重存在』! 将每个厨师拆成Σp[i]个点,每道菜向每个厨师的第i个点连一条流量为1,费用为时间的i倍,每个点向汇点连一条流量为1费用为0的边,跑最小费用最大流 这能跑?不会T到死? 动态加点即可 每个厨师初始只有一个点,如果这个厨师做完了最后一道菜,就添

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

这道题就是"修车"的数据加强版--但是数据范围扩大了好多,应对方法是"动态开点". 首先先把"所有厨师做的倒数第一道菜"和所有菜连边,然后跑一下spfa,找出哪一个厨师在增广路上,把"这个厨师做的倒数第二道菜"和所有菜连边,然后继续spfa,如此循环往复直到spfa找不出最短路. #include <queue> #include <cstdio> #include <cmath> #inc

2879: [Noi2012]美食节 - BZOJ

Description CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽管所有的菜品都很可口,厨师做菜的速度也很快,小M仍然觉得自己桌上没有已经摆在别人餐桌上的美食是一件无法忍受的事情.于是小M开始研究起了做菜顺序的问题,即安排一个做菜的顺序使得同学们的等待时间最短.小M发现,美食节共有n种不同的菜品.每次点餐,每个同学可以选择其中的一个菜品.总共有m个厨师来制作这些菜

BZOJ 2879 美食节(费用流-动态加边)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2879 题意:有n道菜,每道菜需要b[i]份,m个厨师,第j个厨师做第i道菜需要时间a[i][j],求做完所有菜,所有人等待的最小总时间. 思路:设所有的菜为sum.一个明显的思路是将每个厨师拆成sum个点.然后sum个菜每个菜向每个厨师的每个点连边,表示该道菜为该厨师第几个做.由于这样数据太大.动态加边.每次增光一次后找到此次增广的厨师,每道菜将其连边. struct node { i

BZOJ 2878([Noi2012]迷失游乐园-树形DP+环加外向树+期望DP+vector的erase)

2878: [Noi2012]迷失游乐园 Time Limit: 10 Sec  Memory Limit: 512 MBSec  Special Judge Submit: 319  Solved: 223 [Submit][Status] Description 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩.进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐园抽象成有n个景点.m条道路的无向连通图,且该图中至多有一个环(即m只可能等于n或者n-1).小Z现在所在的大门也正好是

BZOJ 2879 NOI 2012 美食节 费用流

题目大意:好长,如果不想看可以先看看修车那个题,基本一样. 思路:做过修车就好办了.这个题仅仅是数据范围变大了一坨.建图就不说了,主要是动态加边.倒过来做,因为一个厨师最后一个菜做的时间是不会影响到其他菜的时间的.而且每一个厨师确定了最后一个菜才能去想倒数第二个菜是什么.所以每跑一次SPFA,就回来看看是哪个厨师做的菜,然后在多加一个点限制一下流量,将这个点连向所有的菜. CODE: #include <queue> #include <cstdio> #include <c

[BZOJ2879] [Noi2012] 美食节 (费用流 &amp; 动态加边)

Description CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他很快就尝遍了美食节所有的美食.然而,尝鲜的欲望是难以满足的.尽管所有的菜品都很可口,厨师做菜的速度也很快,小M仍然觉得自己桌上没有已经摆在别人餐桌上的美食是一件无法忍受的事情.于是小M开始研究起了做菜顺序的问题,即安排一个做菜的顺序使得同学们的等待时间最短.小M发现,美食节共有n种不同的菜品.每次点餐,每个同学可以选择其中的一个菜品.总共有m个厨师来制作这些菜

BZOJ 2878: [Noi2012]迷失游乐园( 树形dp )

一棵树的话直接树形dp(求出往下走和往上走的期望长度). 假如是环套树, 环上的每棵树自己做一遍树形dp, 然后暴力枚举(环上的点<=20)环上每个点跑经过环上的路径就OK了. --------------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm&