题面
解析
这也就是一道费用流的模板题啊!
将S与仓库连边,流量为存货,费用为0,
商店与T连边,流量为需求,费用为0,
(S,T反过来也可以)。
然后把每个仓库与商店连边,
流量为INF,费用为c[i][j],
再spfa+EK求最小费用最大流,最大费用最大流即可(应该不需要证明吧)。
上AC代码:
#include<bits/stdc++.h> using namespace std; inline int read(){ int sum=0,f=1;char ch=getchar(); while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();} return f*sum; } const int INF=0x3f3f3f3f; struct node{ int next,to,w,v; }e[100001]; int n,m,s,t; int head[100001],cnt=1; int a[10001],b[10001],c[1001][1001]; int pre[100001],d[100001],inq[100001],id[100001]; void add(int x,int y,int v,int w){ e[++cnt].to=head[x]; e[cnt].next=y; e[cnt].v=v; e[cnt].w=w; head[x]=cnt; } bool minspfa(){ memset(d,0x3f,sizeof(d)); memset(pre,0,sizeof(pre)); memset(inq,0,sizeof(inq)); int que[100001]={0}; int h=1,tail=1; que[1]=s; d[s]=0; while(h<=tail){ int x=que[h]; inq[x]=0; h++; for(int i=head[x];i;i=e[i].to){ int k=e[i].next; if(e[i].v&&d[k]>d[x]+e[i].w){ pre[k]=x; id[k]=i; d[k]=d[x]+e[i].w; if(!inq[k]) que[++tail]=k; inq[k]=1; } } } return d[t]!=INF; } bool maxspfa(){ memset(d,-0x3f,sizeof(d)); memset(pre,0,sizeof(pre)); memset(inq,0,sizeof(inq)); int que[100001]={0}; int h=1,tail=1; que[1]=s; d[s]=0; while(h<=tail){ int x=que[h]; inq[x]=0; h++; for(int i=head[x];i;i=e[i].to){ int k=e[i].next; if(e[i].v&&d[k]<d[x]+e[i].w){ pre[k]=x; id[k]=i; d[k]=d[x]+e[i].w; if(!inq[k]) que[++tail]=k; inq[k]=1; } } } return d[t]>-1044266559; } void EK1(){ cnt=1; memset(head,0,sizeof(head)); for(int i=1;i<=m;i++){ add(s,i,a[i],0); add(i,s,0,0); for(int j=1;j<=n;j++){ add(i,j+m,INF,c[i][j]); add(j+m,i,0,-c[i][j]); } } for(int i=1;i<=n;i++){ add(i+m,t,b[i],0); add(t,i+m,0,0); } int cost=0; while(minspfa()){ int mi=INF; for(int i=t;i!=s;i=pre[i]){ mi=min(mi,e[id[i]].v); } for(int i=t;i!=s;i=pre[i]){ e[id[i]].v-=mi; e[id[i]^1].v+=mi; } cost+=mi*d[t]; } printf("%d ",cost); } void EK2(){ cnt=1; memset(head,0,sizeof(head)); for(int i=1;i<=m;i++){ add(s,i,a[i],0); add(i,s,0,0); for(int j=1;j<=n;j++){ add(i,j+m,INF,c[i][j]); add(j+m,i,0,-c[i][j]); } } for(int i=1;i<=n;i++){ add(i+m,t,b[i],0); add(t,i+m,0,0); } int cost=0; while(maxspfa()){ int mi=INF; for(int i=t;i!=s;i=pre[i]){ mi=min(mi,e[id[i]].v); } for(int i=t;i!=s;i=pre[i]){ e[id[i]].v-=mi; e[id[i]^1].v+=mi; } cost+=mi*d[t]; } printf("%d ",cost); } int main(){ m=read();n=read(); s=m+n+1;t=m+n+2; for(int i=1;i<=m;i++){ a[i]=read(); } for(int i=1;i<=n;i++){ b[i]=read(); } for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++){ c[i][j]=read(); } } EK1(); EK2(); return 0; }