Libre 6011 「网络流 24 题」运输问题(网络流,最小费用最大流)

mac2022-06-30  23

Libre 6011 「网络流 24 题」运输问题 (网络流,最小费用最大流)

Description

W 公司有m个仓库和n个零售商店。第i个仓库有\(a_i\)个单位的货物;第j个零售商店需要\(b_j\)个单位的货物。货物供需平衡。从第i个仓库运送每单位货物到第j个零售商店的费用为\(c_{ij}\)。试设计一个将仓库中所有货物运送到零售商店的运输方案,使总运输费用最少。

Input

第1行有2个正整数m和n,分别表示仓库数和零售商店数。接下来的一行中有m个正整数\(a_i\),表示第i个仓库\(a_i\)个单位的货物。再接下来的一行中有n个正整数\(b_j\),表示第j个零售商店需要\(b_j\)个单位的货物。接下来的m行,每行有n个整数,表示从第i个仓库运送每单位货物到第j个零售商店的费用\(c_{ij}\)

Output

两行分别输出最小运输费用和最大运输费用。

Sample Input

2 3 220 280 170 120 210 77 39 105 150 186 122

Sample Output

48500 69140

Http

Libre:https://loj.ac/problem/6011

Source

网络流,最小费用最大流

解决思路

这道题的网络流思想还是比较明显的。 对于每一个仓库,从源点连一条容量为该仓库的库存、费用为0的边,对于每一个\(c_{ij}\),连一条仓库i到商店j的边满足容量为无穷大费用为\(c_{ij}\)。再从每一个商店到汇点连一条容量为商店的需求费用为0的边。 然后分别跑最小费用最大流和最大费用最大流即可。

代码

#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long const int maxN=301; const int maxM=maxN*maxN*4; const int inf=2147483647; class Edge { public: int u,v,cost,flow; }; int n,m; int cnt=-1; int A[maxN]; int B[maxN]; int Map[maxN][maxN]; int Head[maxN]; int Next[maxM]; Edge E[maxM]; int Dist[maxN]; int Flow[maxN]; int Q[maxM]; int Path[maxN]; bool inqueue[maxN]; void Add_Edge(int u,int v,int cost,int flow); bool spfa1(); bool spfa2(); int main() { scanf("%d%d",&m,&n); for (int i=1;i<=m;i++) scanf("%d",&A[i]); for (int i=1;i<=n;i++) scanf("%d",&B[i]); for (int i=1;i<=m;i++) for (int j=1;j<=n;j++) scanf("%d",&Map[i][j]); //min最小费用 memset(Head,-1,sizeof(Head)); cnt=-1; for (int i=1;i<=m;i++) Add_Edge(0,i,0,A[i]); for (int i=1;i<=n;i++) Add_Edge(i+m,n+m+1,0,B[i]); for (int i=1;i<=m;i++) for (int j=1;j<=n;j++) Add_Edge(i,j+m,Map[i][j],inf); ll Ans=0; while (spfa1()) { int now=n+m+1; int last=Path[now]; while (now!=0) { E[last].flow-=Flow[n+m+1]; E[last^1].flow+=Flow[n+m+1]; now=E[last].u; last=Path[now]; } Ans+=Dist[n+m+1]*Flow[n+m+1]; } cout<<Ans<<endl; //max最大费用 memset(Head,-1,sizeof(Head)); cnt=-1; for (int i=1;i<=m;i++) Add_Edge(0,i,0,A[i]); for (int i=1;i<=n;i++) Add_Edge(i+m,n+m+1,0,B[i]); for (int i=1;i<=m;i++) for (int j=1;j<=n;j++) Add_Edge(i,j+m,Map[i][j],inf); Ans=0; while (spfa2()) { int now=n+m+1; int last=Path[now]; while (now!=0) { E[last].flow-=Flow[n+m+1]; E[last^1].flow+=Flow[n+m+1]; now=E[last].u; last=Path[now]; } Ans+=Dist[n+m+1]*Flow[n+m+1]; } cout<<Ans<<endl; return 0; } void Add_Edge(int u,int v,int cost,int flow) { cnt++; Next[cnt]=Head[u]; Head[u]=cnt; E[cnt].u=u; E[cnt].v=v; E[cnt].cost=cost; E[cnt].flow=flow; cnt++; Next[cnt]=Head[v]; Head[v]=cnt; E[cnt].u=v; E[cnt].v=u; E[cnt].cost=-cost; E[cnt].flow=0; } bool spfa1() { for (int i=0;i<=n+m+1;i++) Dist[i]=inf; int h=1,t=0; Q[1]=0; inqueue[0]=1; Flow[0]=inf; Dist[0]=0; do { t++; int u=Q[t]; inqueue[u]=0; for (int i=Head[u];i!=-1;i=Next[i]) { int v=E[i].v; if ((E[i].flow>0)&&(Dist[v]>Dist[u]+E[i].cost)) { Dist[v]=Dist[u]+E[i].cost; Flow[v]=min(Flow[u],E[i].flow); Path[v]=i; if (inqueue[v]==0) { h++; Q[h]=v; inqueue[v]=1; } } } } while (h!=t); if (Dist[n+m+1]==inf) return 0; return 1; } bool spfa2() { for (int i=0;i<=n+m+1;i++) Dist[i]=-inf; int h=1,t=0; Q[1]=0; inqueue[0]=1; Flow[0]=inf; Dist[0]=0; do { t++; int u=Q[t]; inqueue[u]=0; for (int i=Head[u];i!=-1;i=Next[i]) { int v=E[i].v; if ((E[i].flow>0)&&(Dist[v]<Dist[u]+E[i].cost)) { Dist[v]=Dist[u]+E[i].cost; Flow[v]=min(Flow[u],E[i].flow); Path[v]=i; if (inqueue[v]==0) { h++; Q[h]=v; inqueue[v]=1; } } } } while (h!=t); if (Dist[n+m+1]==-inf) return 0; return 1; }

转载于:https://www.cnblogs.com/SYCstudio/p/7301415.html

相关资源:JAVA上百实例源码以及开源项目
最新回复(0)