BZOJ_2424_[HAOI2010]订货_最小费用最大流
Description
某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初的库存量为零,第n月月底的库存量也为零,问如何安排这n个月订购计划,才能使成本最低?每月月初订购,订购后产品立即到货,进库并供应市场,于当月被售掉则不必付存贮费。假设仓库容量为S。
Input
第1行:n, m, S (0<=n<=50, 0<=m<=10, 0<=S<=10000)
第2行:U1 , U2 , ... , Ui , ... , Un (0<=Ui<=10000)
第3行:d1 , d2 , ..., di , ... , dn (0<=di<=100)
Output
只有1行,一个整数,代表最低成本
Sample Input
3 1 1000
2 4 8
1 2 4
2 4 8
1 2 4
Sample Output
34
题目描述不清晰,其实可以在某天先卖一点在买的。
也就是说只要求剩下的不超过仓库容量即可。
于是S连第i天(inf,di),第i天连i+1天(inf,m),第i天连T(ui,0)。
跑最小费用最大流即可。
代码:
#include <cstdio> #include <string.h> #include <algorithm> using namespace std; #define N 70 #define M 400050 #define S (n+1) #define T (n+2) #define inf 1<<30 int head[N],to[M],nxt[M],val[M],flow[M],cnt=1,n,m,C; int U[N],D[N],dis[N],path[N],inq[N],Q[N],l,r; void add(int u,int v,int f,int c) { to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; flow[cnt]=f; val[cnt]=c; to[++cnt]=u; nxt[cnt]=head[v]; head[v]=cnt; flow[cnt]=0; val[cnt]=-c; } bool spfa() { memset(dis,0x3f,sizeof(dis)); memset(path,0,sizeof(path)); l=r=0; dis[S]=0; Q[r++]=S; while(l!=r) { int x=Q[l++],i; inq[x]=0; if(l==T) l=0; for(i=head[x];i;i=nxt[i]) { if(dis[to[i]]>dis[x]+val[i]&&flow[i]) { dis[to[i]]=dis[x]+val[i]; path[to[i]]=i^1; if(!inq[to[i]]) { inq[to[i]]=1; Q[r++]=to[i]; if(r==T) r=0; } } } } return path[T]; } void mcmf() { int ans=0,i; while(spfa()) { int nf=1<<30; for(i=T;i!=S;i=to[path[i]]) { nf=min(nf,flow[path[i]^1]); } for(i=T;i!=S;i=to[path[i]]) { ans+=nf*val[path[i]^1]; flow[path[i]]+=nf; flow[path[i]^1]-=nf; } } printf("%d ",ans); } int main() { scanf("%d%d%d",&n,&m,&C); int i; for(i=1;i<=n;i++) scanf("%d",&U[i]); for(i=1;i<=n;i++) scanf("%d",&D[i]); for(i=1;i<=n;i++) { add(S,i,inf,D[i]); add(i,T,U[i],0); if(i!=n) add(i,i+1,C,m); } mcmf(); }