题意:有k种商品,m家供货商,n位顾客。给出每家供货商每种商品的货源,每位顾客对每种商品的需求,每种商品在每对供给中的运费,求每位顾客的要求都能满足时的最小运费。如果无法满足顾客要求,输出-1.
解:对每种商品跑最小费用最大流,然后加上每次的最小费用。如果最大流比顾客需求小,输出-1。建立源点,流向供给商,边权为货源数量;供给商向每位顾客连边,边权为货源数量和运费;顾客向聚点连边,边权为需求,然后跑板子。板子因为inf大小不一样,调了好久。
代码:
1 #include <stdio.h> 2 #include <algorithm> 3 #include <queue> 4 using namespace std; 5 #define maxx 1000005 6 #define maxm 100005 7 #define maxn 5005 8 #define inf 0x3f3f3f3f 9 #define ll long long 10 int n,m,k; 11 int a[55][55],b[55][55],c[55][55][55]; 12 13 int head[maxn],cnt; 14 struct Edge{ 15 int v,w,next,flow; 16 }edge[maxm]; 17 int s,t; 18 int dis[maxn],incf[maxn],pre[maxn],inque[maxn]; 19 int maxflow,mincost; 20 void init(){ 21 memset(head,-1,sizeof(head)); 22 maxflow=mincost=0; 23 cnt=0; 24 } 25 void add(int u,int v,int flow,int cost){ 26 edge[cnt].w=cost; 27 edge[cnt].v=v; 28 edge[cnt].flow=flow; 29 edge[cnt].next=head[u]; 30 head[u]=cnt++; 31 } 32 void addEdge(int u,int v,int flow,int cost){ 33 add(u,v,flow,cost); 34 add(v,u,0,-cost); 35 } 36 int spfa(){ 37 queue<int>q; 38 memset(dis,0x3f,sizeof(dis)); 39 memset(inque,0,sizeof(inque)); 40 q.push(s); dis[s]=0; inque[s]=1; incf[s]=inf; 41 while(!q.empty()){ 42 int u=q.front();q.pop(); 43 inque[u]=0; 44 for(int i=head[u];~i;i=edge[i].next){ 45 if(!edge[i].flow) continue; 46 int v=edge[i].v; 47 if(dis[v]>dis[u]+edge[i].w){ 48 dis[v]=dis[u]+edge[i].w; 49 incf[v]=min(incf[u],edge[i].flow); 50 pre[v]=i; 51 if(!inque[v]){ 52 q.push(v); 53 inque[v]=1; 54 } 55 } 56 } 57 } 58 if(dis[t]==inf) 59 return 0; 60 return 1; 61 } 62 void MCMF(){ 63 while(spfa()){ 64 int x=t; 65 maxflow+=incf[t]; 66 mincost+=dis[t]*incf[t]; 67 int i; 68 while(x!=s){ 69 i=pre[x]; 70 edge[i].flow-=incf[t]; 71 edge[i^1].flow+=incf[t]; 72 x=edge[i^1].v; 73 } 74 } 75 } 76 77 signed main(){ 78 while(~scanf("%d%d%d",&n,&m,&k)) { 79 if(n==0&&m==0&&k==0) 80 break; 81 s=n+m+5,t=s+1; 82 for(int i=1;i<=n;i++) 83 for(int j=1;j<=k;j++) 84 scanf("%d",&a[i][j]); 85 for(int i=1;i<=m;i++) 86 for(int j=1;j<=k;j++) 87 scanf("%d",&b[i][j]); 88 for(int l=1;l<=k;l++) 89 for(int i=1;i<=n;i++) 90 for(int j=1;j<=m;j++) 91 scanf("%d",&c[l][i][j]); 92 int ans=0; 93 for(int l=1;l<=k;l++){ 94 int need=0; 95 init(); 96 for(int i=1;i<=n;i++) 97 addEdge(i,t,a[i][l],0),need+=a[i][l]; 98 for(int i=1;i<=m;i++) 99 addEdge(s,i+n,b[i][l],0); 100 for(int i=1;i<=n;i++) 101 for(int j=1;j<=m;j++) 102 addEdge(j+n,i,b[j][l],c[l][i][j]); 103 MCMF(); 104 if(maxflow<need){ 105 ans=-1; 106 break; 107 } 108 else 109 ans+=mincost; 110 } 111 printf("%d\n",ans); 112 } 113 return 0; 114 }