题目:
Dearboy, a goods victualer, now comes to a big problem, and he needs your help. In his sale area there are N shopkeepers (marked from 1 to N) which stocks goods from him.Dearboy has M supply places (marked from 1 to M), each provides K different kinds of goods (marked from 1 to K). Once shopkeepers order goods, Dearboy should arrange which supply place provide how much amount of goods to shopkeepers to cut down the total cost of transport.
It's known that the cost to transport one unit goods for different kinds from different supply places to different shopkeepers may be different. Given each supply places' storage of K kinds of goods, N shopkeepers' order of K kinds of goods and the cost to transport goods for different kinds from different supply places to different shopkeepers, you should tell how to arrange the goods supply to minimize the total cost of transport.
输入:
The input consists of multiple test cases. The first line of each test case contains three integers N, M, K (0 < N, M, K < 50), which are described above. The next N lines give the shopkeepers' orders, with each line containing K integers (there integers are belong to [0, 3]), which represents the amount of goods each shopkeeper needs. The next M lines give the supply places' storage, with each line containing K integers (there integers are also belong to [0, 3]), which represents the amount of goods stored in that supply place.
Then come K integer matrices (each with the size N * M), the integer (this integer is belong to (0, 100)) at the i-th row, j-th column in the k-th matrix represents the cost to transport one unit of k-th goods from the j-th supply place to the i-th shopkeeper.
The input is terminated with three "0"s. This test case should not be processed.
输出:
For each test case, if Dearboy can satisfy all the needs of all the shopkeepers, print in one line an integer, which is the minimum cost; otherwise just output "-1".
样例输入:
1 3 3 1 1 1 0 1 1 1 2 2 1 0 1 1 2 3 1 1 1 2 1 1 1 1 1 3 2 20 0 0 0
样例输出:
4 -1
有N个店主,M个供应商,K种不同的商品。每个店主所需要的不同的商品的数量不一样,每个供应商所能提供的不同的商品的数量也不一样,不同的供应商到不同的店主所需要花费的费用也不一样。因为每个商家和每个供应商所需要的和所能提供的商品数量不一样,所以分物品来建图。
在最外面定义一个循环,循环k种商品,建立超级源点和超级汇点,让供应商和超级源点连接,容量为供应商所能提供的这件商品的数量,费用为0;让店主和超级汇点连接,容量为店主所需要这件商品的数量,费用为0;最后把供应商和店主连接起来,容量至少为k(因为有k种商品),费用为每个供应商到每个店主所对应的费用。
AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=100000;
const int INF=0x7fffffff;
int n,m,k,cnt,value,flow,s,t;
int head[maxn],dis[maxn],d[maxn],p[maxn],f[maxn];//d表示原点到各个点的费用;p表示这个点的前点;f表示这条路径上的最小流量
int poss[60][60],needs[60][60],start[maxn],endd[maxn],jz[60][60][60];//poss表示供应商有的;needs表示店主需要的;endd表示所有店主需要的某种商品的数量;start表示所有供应商拥有的某种商品的数量
struct edge
{
int u,v,c,w,next;
}node[maxn];
void add(int u,int v,int c,int w)
{
node[cnt].u=u;
node[cnt].v=v;
node[cnt].c=c;
node[cnt].w=w;
node[cnt].next=head[u];
head[u]=cnt++;
}
int spfa()
{
queue<int>q;
for(int i=0;i<maxn;i++)d[i]=INF;//因为要找最短,所以初始化为最大
memset(dis,0,sizeof(dis));
memset(p,-1,sizeof(p));
q.push(s);
dis[s]=1;
d[s]=0;//源点到源点本身为0
p[s]=0;f[s]=INF;//因为要找一条路径上最小的流量,所以流量初始化为最大
while(!q.empty())
{
int u=q.front();
q.pop();
dis[u]=0;
for(int i=head[u];i!=-1;i=node[i].next)
{
edge e=node[i];
if(d[e.v]>d[e.u]+e.w&&e.c>0)
{
d[e.v]=d[e.u]+e.w;
p[e.v]=i;
f[e.v]=min(f[u],e.c);
if(!dis[e.v])
{
q.push(e.v);
dis[e.v]=1;
}
}
}
}
if(p[t]==-1)return 0;
flow+=f[t];value+=f[t]*d[t];
for(int i=t;i!=s;i=node[p[i]].u)
{
node[p[i]].c-=f[t];
node[p[i]^1].c+=f[t];
}
return 1;
}
int maxflow()
{
value=0;
flow=0;
while(spfa());//这个循环进行完了value就是一件商品最大流的最小费用
return value;
}
int main()
{
while(scanf("%d%d%d",&n,&m,&k)!=EOF &&n+m+k)
{
int ans=0;
int ok=1;
s=0;//超级源点和汇点
t=(n+m)*2+100;
memset(start,0,sizeof(start));
memset(endd,0,sizeof(endd));
for(int i=1;i<=n;i++)
for(int j=1;j<=k;j++)
{
scanf("%d",&needs[i][j]);
endd[j]+=needs[i][j];
}
for(int i=1;i<=m;i++)
for(int j=1;j<=k;j++)
{
scanf("%d",&poss[i][j]);
start[j]+=poss[i][j];
}
for(int i=1;i<=k;i++)
for(int j=1;j<=n;j++)
for(int l=1;l<=m;l++)
{
scanf("%d",&jz[i][j][l]);
}
for(int i=1;i<=k;i++)
{
if(endd[i]>start[i])
{
printf("-1\n");
ok=0;
break;
}
}
if(!ok) continue;
for(int i=1;i<=k;i++)
{
memset(head,-1,sizeof(head));
cnt=0;
for(int j=1;j<=n;j++)
{
add(j,t,needs[j][i],0);
add(t,j,0,0);
}
for(int l=1;l<=m;l++)
{
add(s,n+l,poss[l][i],0);
add(n+l,s,0,0);
}
for(int j=1;j<=m;j++)
for(int l=1;l<=n;l++)
{
add(n+j,l,k,jz[i][l][j]);
add(l,n+j,0,-jz[i][l][j]);
}
ans+=maxflow();
}
printf("%d\n",ans);
}
return 0;
}