原题链接:https://www.luogu.org/problemnew/show/P4015
会写费用流了好开心啊。。。
题意简述:有m个仓库,第i个仓库有a[i]个货物,n个商店,第i个商店需要b[i]件货物。
第i个仓库向第j个商店运一件货物的价格为d[i][j]。
求最少花费。
费用流板子题。
1-m表示仓库,m+1-m+n表示商店。
源点向仓库连流量为a[i],费用0,商店向汇点连边,流量b[i],费用0
第i个仓库向第j个商店连边,费用d[i][j],流量>=a[i]即可
非常直接的建边方式。。。然后就是费用流板子了
#include<cstdio> #include<queue> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int inf=2147483647; void read(int &y) { y=0;char x=getchar(); int f=1; while(x<‘0‘||x>‘9‘) x=getchar(); while(x>=‘0‘&&x<=‘9‘) { y=y*10+x-‘0‘; x=getchar(); } } struct edge { int u,v,w,c; int frm; }e[100005]; int m,n,s,cnt=1,t=201; int fr[1005],head[2005],vis[2005],dis[2005]; int a[1005],b[1005]; int d[105][105]; long long ans; void add(int u,int v,int w,int c) { e[++cnt].u=head[u];e[cnt].v=v; e[cnt].w=w;e[cnt].c=c; e[cnt].frm=u;head[u]=cnt; e[++cnt].u=head[v];e[cnt].v=u; e[cnt].w=0;e[cnt].c=-c; e[cnt].frm=v;head[v]=cnt; } int dfs() { int re=0,x=inf; for(int i=fr[t];i;i=fr[e[i].frm]) x=min(e[i].w,x); for(int i=fr[t];i;i=fr[e[i].frm]) { e[i].w-=x; e[i^1].w+=x; re+=x*e[i].c; } return re; } int spfa() { for(int i=1;i<=t;i++) dis[i]=inf; memset(vis,0,sizeof(vis)); queue<int>q; q.push(s); vis[s]=1;dis[s]=0; while(!q.empty()) { int nxt=q.front();q.pop(); for(int i=head[nxt];i!=-1;i=e[i].u) { int tmp=e[i].v; if(dis[tmp]>dis[nxt]+e[i].c&&e[i].w) { dis[tmp]=dis[nxt]+e[i].c; fr[tmp]=i; if(vis[tmp]==0) { vis[tmp]=1; q.push(tmp); } } } vis[nxt]=0; } if(dis[t]==inf) return 0; return 1; } int main() { read(m);read(n); for(int i=1;i<=m;i++) read(a[i]); for(int i=1;i<=n;i++) read(b[i]); int x; for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) read(d[i][j]); } memset(head,-1,sizeof(head)); for(int i=1;i<=m;i++) add(s,i,a[i],0); for(int i=1;i<=n;i++) add(m+i,t,b[i],0); for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) add(i,m+j,inf,d[i][j]); } while(spfa()) ans+=dfs(); printf("%lld\n",ans); memset(head,-1,sizeof(head)); cnt=1;ans=0; for(int i=1;i<=m;i++) add(s,i,a[i],0); for(int i=1;i<=n;i++) add(m+i,t,b[i],0); for(int i=1;i<=m;i++) { for(int j=1;j<=n;j++) add(i,m+j,inf,-d[i][j]); } while(spfa()) ans+=dfs(); printf("%lld",-ans); return 0; }