题意:
Acme公司生产一种X元素,给出该元素在未来M个月中每个月的单位售价、最大产量、最大销售量,以及最大储存时间(过期报废不过可以储存任意多的量)。你的任务是计算出公司能够赚到的最大利润。
分析:
把第i个月拆成i1和i2两个点,连一条s到i1的弧,容量为i月最大产量,费用为单位成本。连一条i2到t的弧,容量为最大销量,费用为单位售价的相反数。然后i1向i2连一条容量为INF费用为0的弧,代表当月销售。i1向其他j2连弧,容量为INF,费用为储藏代价。
另外,这个题属于流量不固定的最小费用流。也就是说,并不是一定要跑到最大流。用spfa寻找增广路的时候,当d[t]>0的时候就要停止增广。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <iostream> 5 #include <queue> 6 #include <vector> 7 8 using namespace std; 9 typedef long long LL; 10 const int maxn=300+10; 11 const int maxm=40000+10; 12 const int INF=2147000000; 13 14 struct MCMF{ 15 int head[maxn],to[maxm],Next[maxm],from[maxm],cost[maxm],flow[maxm],cap[maxm]; 16 int n,m,s,t,sz; 17 int inq[maxn]; 18 int d[maxn]; 19 int p[maxn]; 20 int a[maxn]; 21 22 void init(int n){ 23 this->n=n; 24 sz=-1; 25 memset(head,-1,sizeof(head)); 26 } 27 void AddEdge(int a,int b,int ca,int co){ 28 ++sz; 29 to[sz]=b,from[sz]=a,Next[sz]=head[a],head[a]=sz; 30 flow[sz]=0,cap[sz]=ca,cost[sz]=co; 31 ++sz; 32 to[sz]=a,from[sz]=b,Next[sz]=head[b],head[b]=sz; 33 flow[sz]=ca,cap[sz]=ca,cost[sz]=-co; 34 } 35 bool BellmanFord(int s,int t,int &Flow,LL &Cost){ 36 for(int i=0;i<=n;i++)d[i]=INF; 37 memset(inq,0,sizeof(inq)); 38 d[s]=0;inq[s]=1;p[s]=-1;a[s]=INF; 39 queue<int>Q; 40 Q.push(s); 41 while(!Q.empty()){ 42 int u=Q.front();Q.pop(); 43 inq[u]=0; 44 for(int i=head[u];i!=-1;i=Next[i]){ 45 int v=to[i]; 46 if(cap[i]>flow[i]&&d[v]>d[u]+cost[i]){ 47 d[v]=d[u]+cost[i]; 48 p[v]=i; 49 a[v]=min(a[u],cap[i]-flow[i]); 50 if(!inq[v]){ 51 Q.push(v); 52 inq[v]=1; 53 } 54 } 55 } 56 } 57 if(d[t]==INF||d[t]>0)return false; 58 Flow+=a[t]; 59 Cost+=(LL)d[t]*(LL)a[t]; 60 int u=t; 61 62 while(u!=s){ 63 flow[p[u]]+=a[t]; 64 flow[p[u]^1]-=a[t]; 65 u=from[p[u]]; 66 } 67 return true; 68 } 69 70 LL Mincost(int s,int t){ 71 int Flow=0;LL Cost=0; 72 while(BellmanFord(s,t,Flow,Cost)); 73 return Cost; 74 } 75 }mcmf; 76 const int maxM=150; 77 int T,M,I,kase; 78 int m[maxM],n[maxM],p[maxM],s[maxM],E[maxM]; 79 80 int main(){ 81 scanf("%d",&T); 82 // freopen("out.txt","w",stdout); 83 kase=0; 84 for(int t=1;t<=T;t++){ 85 ++kase; 86 scanf("%d%d",&M,&I); 87 mcmf.init(2*M+2); 88 mcmf.s=0;mcmf.t=2*M+1; 89 for(int i=1;i<=M;i++){ 90 scanf("%d%d%d%d%d",&m[i],&n[i],&p[i],&s[i],&E[i]); 91 mcmf.AddEdge(0,i,n[i],m[i]); 92 mcmf.AddEdge(i+M,2*M+1,s[i],-p[i]); 93 for(int j=0;j+i<=M&&j<=E[i];j++){ 94 mcmf.AddEdge(i,i+j+M,INF,j*I); 95 } 96 } 97 LL ans=mcmf.Mincost(0,2*M+1); 98 printf("Case %d: %lld ",kase,-ans); 99 } 100 return 0; 101 }