n个店主,m个经销商,k个商品。不同经销商可以提供不同数量的商品,不同店主需求不同数量的商品,不同的商品从不同的店主手中发货给不同的店主需要花费不同的价钱。
题目输入格式是这样的:
第一行n m k
接下来是一个n*k的矩阵,表示不同店主需求不同数量的商品;
然后是一个m*k的矩阵,表示不同经销商可以提供不同数量的商品;
最后是k个n*m的矩阵,表示不同的商品从不同的店主手中发货给不同的店主需要花费不同的价钱;
很显然是一道最小费用最大流的问题。
直接求所有物品从所有供应商运送到所有店主的最小费用,不好操作。所以把阶段分为k个,每个阶段求一件商品的从所有供应商运送到所有店主的最小费用。这样就容易处理一些。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define INF 0x7fffffff
using namespace std;
int N,M,K,need[60][60],prov[60][60],cost[60][60],val[300][300],n,dis[300][300],pre[300],dist[300],ans,check_ans;
int s1,e1,s2,e2;
int min(int a,int b)
{
return a>b?b:a;
}
int spfa()
{
int u,v;
bool inque[300];
queue<int> q;
while (!q.empty())
q.pop();
memset(dist,-1,sizeof(dist));
memset(inque,false, sizeof(inque));
dist[1]=0;
inque[1]=true;
q.push(1);
while (!q.empty())
{
u=q.front();
q.pop();
inque[u]=false;
for (v=1; v<=n; v++)
{
if (val[u][v] != 0 && (dist[v] == -1 || dist[v] > dist[u]+dis[u][v]))
{
dist[v]=dist[u]+dis[u][v];
pre[v]=u;
if (inque[v] == false)
{
inque[v]=true;
q.push(v);
}
}
}
}
return dist[n];
}
bool slove()
{
int i,flow,tmp;
flow=INF;
tmp=0;
while (spfa() != -1)
{
for (i=n; i != 1; i=pre[i])
{
flow=min(flow,val[pre[i]][i]);
}
for (i=n; i != 1; i=pre[i])
{
val[pre[i]][i]-=flow;
val[i][pre[i]]+=flow;
ans+=flow*dis[pre[i]][i];
}
tmp+=flow;
}
if (tmp == check_ans)
return true;
else
return false;
}
int main()
{
int i,j,k,l,o;
bool flag;
while (1)
{
scanf("%d%d%d",&N,&M,&K);
ans=0;
if (N == 0 && M == 0 && K == 0)
break;
for (i=1; i<=N; i++)
{
for (j=1; j<=K; j++)
{
scanf("%d",&need[i][j]);
}
}
for (i=1; i<=M; i++)
{
for (j=1; j<=K; j++)
{
scanf("%d",&prov[i][j]);
}
}
flag=true;
for (i=1; i<=K; i++)
{
for (j=1; j<=N; j++)
{
for (k=1; k<=M; k++)
{
scanf("%d",&cost[j][k]);
}
}
if (flag == false)
continue;
s1=2;
e1=1+M;
s2=2+M;
e2=1+M+N;
n=e2+1;
check_ans=0;
memset(val,0,sizeof(val));
memset(dis,0,sizeof(dis));
for (j=s1,k=1; j<=e1; j++,k++)
{
val[1][j]=prov[k][i];
}
for (j=s1,l=1; j<=e1; j++,l++)
{
for (k=s2,o=1; k<=e2; k++,o++)
{
val[j][k]=prov[l][i];
dis[j][k]=cost[o][l];
dis[k][j]=-cost[o][l];
}
}
for (j=s2,k=1; j<=e2; j++,k++)
{
val[j][n]=need[k][i];
check_ans+=need[k][i];
}
if (slove() == false)
{
flag=false;
}
}
if (flag == true)
printf("%d\n",ans);
else
printf("-1\n");
}
}