题面

传送门

思路

先看看这道题

修车

仔细理解一下,这两道题是不是一样的?

这道题的不同之处

但是有一个区别:本题中每一种车有多个需求,但是这个好办,连边的时候容量涨成$p\lbrack i\rbrack$就好了

但是还有一个区别:数据量变大了-_-

这直接导致了费用流裸做,TLE60分,因为有超过6e6条边

我们得想个办法改进一下

观察可得,这道题里,按照我们的模型,最多出现800条增广路,而且每次增广都是一的流量

也就是说我们实际上跑800次spfa即可

但是spfa和边唯一相关,我们全建好的图中6e6*800*k肯定会T

那我们就要想个办法优化边数

优化

我们观察发现,第一次spfa得出的最短路肯定是某人倒数第一个修某车某厨师倒数第一个做某菜,因为倒数第一个肯定比倒数第二个距离短

那么我们可以在一开始建图的时候,只把所有“倒数第一个做的菜”的那些边加上

一旦一条增广路被用掉了(也就是一个厨师-做菜顺序二元组$\left(j,k\right)$被用掉了),那么我们就把所有代表二元组$\left(j,k+1\right)$加上去(一共有n条),再跑spfa

这样我们图中的总边数不会超过$n\ast\sum_{i=1}^n p\lbrack i\rbrack$

也就是总时间在$O\left(np^2\ast k\right)$左右,k是spfa常数

这样就可以过了

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define inf 1e9
#define id(i,j) ((i-1)*p+j+n)
#define left(x) ((x-n-1)/p+1)
#define right(x) ((x-n-1)%p+1)
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(ch>'9'||ch<'0'){
if(ch=='-') flag=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
int n,m,cnt=-1,first[100010],dis[100010],vis[100010],pre[100010],limit[100010];
struct edge{
int to,next,w,cap;
}a[10000010];
inline void add(int u,int v,int w,int cap){
a[++cnt]=(edge){v,first[u],w,cap};first[u]=cnt;
a[++cnt]=(edge){u,first[v],-w,0};first[v]=cnt;
}
int q[200010],ans,cost[50][110],p;
bool spfa(int s,int t){
int head=0,tail=1,u,v,w,i;
memset(dis,-1,sizeof(dis));memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));memset(limit,0,sizeof(limit));
q[0]=s;vis[s]=1;dis[s]=0;limit[s]=inf;
while(head<tail){
u=q[head++];vis[u]=0;
for(i=first[u];~i;i=a[i].next){
v=a[i].to;w=a[i].w;
if(a[i].cap&&((dis[v]==-1)||(dis[v]>dis[u]+w))){
dis[v]=dis[u]+w;
pre[v]=i;limit[v]=min(limit[u],a[i].cap);
if(!vis[v]) q[tail++]=v,vis[v]=1;
}
}
}
return ~dis[t];
}
void mcmf(int s,int t){
int u,i;
while(spfa(s,t)){//这里最多sigma(p[i])次
for(u=t;~pre[u];u=a[pre[u]^1].to){
a[pre[u]].cap-=limit[t];a[pre[u]^1].cap+=limit[t];
ans+=limit[t]*a[pre[u]].w;
}//跑完一次更新答案
u=a[pre[t]^1].to;//u就是当前消耗的二元组,u+1就是下一个二元组
add(u+1,t,0,1);
for(i=1;i<=n;i++) add(i,u+1,cost[i][left(u+1)]*right(u+1),1);//加上对应的下一组边
}
}
int main(){
memset(first,-1,sizeof(first));int i,j,t1;
n=read();m=read();
for(i=1;i<=n;i++){
t1=read();p+=t1;
add(0,i,0,t1);
}
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
cost[i][j]=read();
add(i,id(j,1),cost[i][j],1);//初始边
}
}
for(j=1;j<=m;j++) add(id(j,1),n+p*m+1,0,1);
mcmf(0,n+p*m+1);
cout<<ans<<endl;
}

[NOI2012][bzoj2879] 美食节 [费用流+动态加边]的更多相关文章

  1. 【bzoj2879】[Noi2012]美食节 费用流+动态加边

    原文地址:http://www.cnblogs.com/GXZlegend 题目描述 CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他 ...

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

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

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

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

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

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2879 题意:有n道菜,每道菜需要b[i]份,m个厨师,第j个厨师做第i道菜需要时间a[i ...

  5. [BZOJ1070] [SCOI2007] 修车 (费用流 & 动态加边)

    Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使 ...

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

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

  7. [NOI2012]美食节——费用流(带权二分图匹配)+动态加边

    题目描述 小M发现,美食节共有n种不同的菜品.每次点餐,每个同学可以选择其中的一个菜品.总共有m个厨师来制作这些菜品.当所有的同学点餐结束后,菜品的制作任务就会分配给每个厨师.然后每个厨师就会同时开始 ...

  8. [NOI2012]美食节(费用流)

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

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

    思路同修车,就是多了一个骚气的操作:动态加边,我们通过spfa流的过程可以知道,我们一次只会跑一流量,最后一层边跑过就不会再悔改,所以说我们只会用到一大片里面的很少的点,所以我们如果可以动态加边的话我 ...

随机推荐

  1. Shuffle Cards

    C: Shuffle Cards 时间限制: 1 Sec  内存限制: 128 MB提交: 3  解决: 3[提交] [状态] [讨论版] [命题人:admin] 题目描述 Eddy likes to ...

  2. CentOS6.5-DHCP配置

    原文链接主机配置: 1.查看主机名:hostname 2.修改主机名:vi /etc/sysconfig/network NETWORKING=yes HOSTNAME=master.303kfy.n ...

  3. c++ bitset 10进制转二进制

    #include <bitset> using namespace std; void main() { int a; cin>>a; cout<<bitset&l ...

  4. 牛客小白月赛5 A 无关(relationship) 【容斥原理】【数据范围处理】

    题目链接:https://www.nowcoder.com/acm/contest/135/A 题目描述 若一个集合A内所有的元素都不是正整数N的因数,则称N与集合A无关.   给出一个含有k个元素的 ...

  5. 2.3.3 zerosum 和为零

    #include<bits/stdc++.h> using namespace std; ],a; ]={' ','+','-'}; void out() { ;i<a;i++) c ...

  6. 【PHP】什么时候使用Try Catch(转)

    几条建议: 如果无法处理某个异常,那就不要捕获它.  如果捕获了一个异常,请不要胡乱处理它.  尽量在靠近异常被抛出的地方捕获异常.  在捕获异常的地方将它记录到日志中,除非您打算将它重新抛出.  按 ...

  7. 【css】如何实现响应式布局

    “自适应网页设计”到底是怎么做到的?其实并不难. 首先,在网页代码的头部,加入一行viewport元标签. <meta name="viewport" content=&qu ...

  8. 第48课 thinkphp5添加商品库

    目录 思路: 1. html页面里属性下拉框里的值是从goods_attr联attr里的查出来传到模板里的.在属性的下拉栏里展示出来 2. html页面里用二维数组的结构goods_attr[{$k} ...

  9. python3.7 迭代器和生成器

    #!/usr/bin/env python __author__ = "lrtao2010" #python3.7 迭代器和生成器 #迭代器协议: ''' 1.迭代器协议是指:对象 ...

  10. D3DXCreateTexture

    HRESULT D3DXCreateTexture( __in LPDIRECT3DDEVICE9 pDevice, __in UINT Width, __in UINT Height, __in U ...