[BZOJ 2424][HAOI2010]订货(费用流)
Description
某公司估计市场在第i个月对某产品的需求量为Ui,已知在第i月该产品的订货单价为di,上个月月底未销完的单位产品要付存贮费用m,假定第一月月初的库存量为零,第n月月底的库存量也为零,问如何安排这n个月订购计划,才能使成本最低?每月月初订购,订购后产品立即到货,进库并供应市场,于当月被售掉则不必付存贮费。假设仓库容量为S。
Solution
一道建图比较明显的费用流
从s向每一天i连容量为INF费用为di的边
从每一天i向t连容量为ui费用为0的边
每一天向下一天连容量为S费用为m的边
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<queue> #define INF 0x3f3f3f3f using namespace std; int n,m,S,s,t; int head[505],cnt=0,a[505],dis[505],pre[505]; bool inq[505]; int read() { int x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1;c=getchar(); } while(c>='0'&&c<='9'){ x=x*10+c-'0';c=getchar(); } return x*f; } struct Node { int next,from,to,cap,w; }Edges[5005]; void addedge(int u,int v,int c,int w) { Edges[cnt].next=head[u]; head[u]=cnt; Edges[cnt].from=u; Edges[cnt].to=v; Edges[cnt].cap=c; Edges[cnt++].w=w; } void insert(int u,int v,int c,int w) { addedge(u,v,c,w); addedge(v,u,0,-w); } queue<int>q; int MCMF() { int flow=0,cost=0; while(1) { memset(a,0,sizeof(a)); memset(dis,0x3f,sizeof(dis)); q.push(s); a[s]=INF,dis[s]=0,inq[s]=1,pre[s]=-1; while(!q.empty()) { int u=q.front(); q.pop(),inq[u]=0; for(int i=head[u];~i;i=Edges[i].next) { int v=Edges[i].to; if(dis[v]>dis[u]+Edges[i].w&&Edges[i].cap>0) { dis[v]=dis[u]+Edges[i].w; a[v]=min(a[u],Edges[i].cap); pre[v]=i; if(!inq[v]) inq[v]=1,q.push(v); } } } if(!a[t])break; flow+=a[t],cost+=a[t]*dis[t]; int p=t; while(pre[p]!=-1) { Edges[pre[p]].cap-=a[t]; Edges[pre[p]^1].cap+=a[t]; p=Edges[pre[p]].from; } } return cost; } int main() { memset(head,-1,sizeof(head)); n=read(),m=read(),S=read(); s=0,t=n+1; for(int i=1;i<=n;i++) { int u=read(); insert(i,t,u,0); } for(int i=1;i<=n;i++) { int d=read(); insert(s,i,INF,d); if(i!=n)insert(i,i+1,S,m); } printf("%d\n",MCMF()); return 0; }