[NOI2012]【网络流】美食节

题目描述:

有N个厨师M道菜,每个厨师烧第I道菜要C[I]分钟,问所以菜至少一共等多久?

口胡题解:

为了做过的方便回忆所以题面大概这样,但是有很多小细节还要回去看。

先确定基本框架:一个人在不同的状态下可以做不同菜,但是时间会因为你越往后做而累加,这容易让人望分层图上靠,但具体做法又不是很清楚。。

我们先考虑不同的顺序造成不同的影响:

假设有三道菜1,2,3;有一位厨师X,做菜时间分别为C1,C2,C3。
若这位厨师以213顺序做菜,则总贡献为C2*3+C1*2+C3;
若这位厨师以321顺序做菜,则总贡献为C3*3+C2*2+C1;
....

通过以上例子应该就能想到,越在前面做的菜贡献越多,可以把那个系数定义为时间戳

也就是说在一个时间戳I做要花费C的菜造成的贡献为I*C,那我们就可以对时间戳分层啦!

其他建图都是常规,我们将一个厨师拆成N个点,分别表示在第i个时间戳的厨师。每个厨师都可以向所有菜连边,容量1,然后费用就是i*c[j]

上述样例应该长这样:

因为容量是1,所以每个时间戳都只会经过一次,这样就OK啦!

但是这道题要优化?

我们发现这题的点也太多了,开了O2才跑60分,这咋爆裂啊??

我们发现之所以这么慢都怪连点太多了,而且太多的状态浪费掉了。

我们依然举例子:

假设有2道菜{1,2,3},2个厨师{A,B},分别时间是C[I][J],让他们比个赛。
1.假如我们只考虑整个厨房的第一道菜的状况,发现第一个做完第一道菜的是我们的A,他做了1号菜,于是我们继续往后跑A在第二个时间戳的情况。
但我们发现,此时B还没开始做菜呢!于是此时我们先不急着把B的第二个时间戳加上,还是让他跑第一个时间戳。

2.于是让比赛继续,我们发现整个厨房做完第二道菜还是A,他又把2号菜给做了。
你可能会问为啥B到现在都没开始做菜?可能是因为他太菜了,所以做啥菜都慢。。所以我们给A加到第三个时间戳,B仍是第一个。

3.比赛继续,我们发现第三道菜终于是B做了!他做的是3号菜!
裁判很是感动但并没有给他加上第二个时间戳,因为3道菜全做完了比赛结束,B从头到尾就没有加过新的时间戳。。

由上例子我们可看出,本来应该2*3个时间戳,如今只剩下了3个,而那便是菜的总数!!

这是多么优良的优化!用图论的说法就是:我们每次跑费用流找增广路的时候,仅增加当前厨师的时间戳,其他厨师等你把当前时间戳的菜做完了再加,这样就可以大大减少不必要的浪费了!

当然也很显然的可以看出,这是基于EK分析的,但如果是Dinic的多路增广也同样适用。

然后就可以AC啦!