bzoj2424: [HAOI2010]订货(费用流)
2424: [HAOI2010]订货
题目:传送门
题解:
做多了最小割,做一下费用流练手
其实很容易就看出来是费用流啊,伏地魔肉老师用单调队列ORZ
st直接连每个月,流量无限(随便买,花钱而已),费用就是给出来的
然后因为可以贮存嘛,那就第i个月连第i+1个月,流量为S(仓库容量),费用为m就OK
最后就是卖出去咯,第i个月连ed流量为需要的,费用为0
难受,打个spfa忘记出队列...
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #define inf 999999999 7 using namespace std; 8 struct node 9 { 10 int x,y,c,d,next,other; 11 }a[1100];int len,last[110]; 12 void ins(int x,int y,int c,int d) 13 { 14 int k1,k2; 15 k1=++len; 16 a[len].x=x;a[len].y=y;a[len].c=c;a[len].d=d; 17 a[len].next=last[x];last[x]=len; 18 19 k2=++len; 20 a[len].x=y;a[len].y=x;a[len].c=0;a[len].d=-d; 21 a[len].next=last[y];last[y]=len; 22 23 a[k1].other=k2; 24 a[k2].other=k1; 25 } 26 int list[11000],la[11000],d[11000],st,ed,n,m,head,tail,ans,S; 27 bool v[11000]; 28 bool spfa() 29 { 30 for(int i=1;i<=ed;i++)d[i]=inf; 31 memset(v,false,sizeof(v));memset(la,0,sizeof(la)); 32 list[1]=st;d[st]=0;v[st]=true;head=1;tail=2; 33 while(head!=tail) 34 { 35 int x=list[head]; 36 for(int k=last[x];k;k=a[k].next) 37 { 38 int y=a[k].y; 39 if(a[k].c>0 && d[y]>d[x]+a[k].d) 40 { 41 d[y]=d[x]+a[k].d;la[y]=k; 42 if(v[y]==false) 43 { 44 v[y]=true; 45 list[tail++]=y; 46 if(tail==ed+1)tail=1; 47 } 48 } 49 } 50 head++;if(head==ed+1)head=1; 51 v[x]=false; 52 } 53 if(d[ed]==inf)return false; 54 return true; 55 } 56 int g_f() 57 { 58 int x,k,f=inf,ans=0; 59 x=ed;while(x!=st){k=la[x];f=min(f,a[k].c);x=a[k].x;} 60 x=ed;while(x!=st){k=la[x];ans+=f*a[k].d;a[k].c-=f;a[a[k].other].c+=f;x=a[k].x;} 61 return ans; 62 } 63 int A[110],B[110]; 64 int main() 65 { 66 scanf("%d%d%d",&n,&m,&S);len=0;memset(last,0,sizeof(last));st=n+1,ed=st+1; 67 for(int i=1;i<=n;i++)scanf("%d",&A[i]); 68 for(int i=1;i<=n;i++)scanf("%d",&B[i]); 69 for(int i=1;i<=n;i++)ins(st,i,inf,B[i]); 70 for(int i=1;i<=n;i++){if(i!=n)ins(i,i+1,S,m);ins(i,ed,A[i],0);} 71 int ans=0;while(spfa())ans+=g_f(); 72 printf("%d\n",ans); 73 return 0; 74 }