题目链接:http://poj.org/problem?id=2516
这道题有点呕。
题目大概意思:
现在有n个店主,m个供应商,k个商品。
现在给你n*k的矩阵,表示每个店主对于每个商品的需求量。
然后给你m*k的矩阵,表示每个供应商每个物品的拥有量。
然后给你k个n*m的矩阵,表示每个商品在每个供应商和商人之间的消费。
最后求能否满足所有店主都能得到满足,如果可以输出最小费用,否则输出-1.
建图就是对于每个商品都建图。
这个样子。
代码:
import java.util.*;
import java.io.*;
import java.math.*;
public class Main {
static StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
static PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
static final int inf=1<<30;
static int v,m,s,t,f; //f是最大流量
static ArrayList g[];
static int len;
static int dist[];
static int prevv[];
static int preve[];
static int h[];
static void addEdge(int from,int to,int cap,int cost) {
//System.out.println(from+" "+to+" "+cap+" "+cost);
g[from].add(new Edge(to,cap,cost,g[to].size()));
g[to].add(new Edge(from,0,-cost,g[from].size()-1));
}
static int min_cost(int s,int t) {
int res=0;
for(int i=0;i<=v;i++)
h[i]=0;
while(true) {
for(int i=0;i<=v;i++)
dist[i]=inf;
dist[s]=0;
PriorityQueue list=new PriorityQueue
();
list.offer(new P(0,s));
while(!list.isEmpty()) {
P p=list.poll();
int v=p.b;
if(dist[v]
0&&dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]) {
dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
prevv[e.to]=v; //保存前驱
preve[e.to]=i; //当点在前驱节点对应的位置
list.add(new P(dist[e.to],e.to));
}
}
}
if(dist[t]==inf)
break;
for(int u=1;u<=v;u++)
h[u]+=dist[u];
int d=inf;
for(int v=t;v!=s;v=prevv[v]) {
d=Math.min(d,g[prevv[v]].get(preve[v]).cap);
}
f+=d;
res+=d*h[t];
for(int v=t;v!=s;v=prevv[v]) {
Edge e=g[prevv[v]].get(preve[v]);
e.cap-=d;
g[v].get(e.rev).cap+=d;
}
}
return res;
}
static void init() {
h=new int[v+1];
f=0;
g=new ArrayList[v+1];
for(int i=0;i<=v;i++) {
g[i]=new ArrayList();
}
dist=new int[v+1];
prevv=new int[v+1];
preve=new int[v+1];
}
public static void main(String[] args) throws Exception{
Scanner sc=new Scanner(System.in);
p:while(true) {
//System.out.println("--");
int a=getInt();
int b=getInt();
int c=getInt(); //店主,供货点,商品个数
if(a+b+c==0)break;
v=a+b+2;
int arr1[][]=new int[a+1][c+1]; //需求量
for(int i=1;i<=a;i++)
for(int j=1;j<=c;j++)
arr1[i][j]=getInt(); //存货量
int arr2[][]=new int[b+1][c+1];
for(int i=1;i<=b;i++)
for(int j=1;j<=c;j++)
arr2[i][j]=getInt();
int arr3[][][]=new int[c+1][a+1][b+1];
for(int i=1;i<=c;i++)
for(int j=1;j<=a;j++)
for(int k=1;k<=b;k++)
arr3[i][j][k]=getInt();
int ans=0;
for(int i=1;i<=c;i++) {
s=0;
v=2+a+b;
t=v-1;
init();
int sum=0;
for(int j=1;j<=a;j++) { //店主和货物
addEdge(s,j,arr1[j][i],0);
sum+=arr1[j][i];
}
for(int j=1;j<=b;j++) { //供应商和汇点
addEdge(a+j,t,arr2[j][i],0);
}
for(int j=1;j<=a;j++)
for(int k=1;k<=b;k++)
addEdge(j,a+k,arr2[k][i],arr3[i][j][k]);
int d=min_cost(s,t);
if(f!=sum) {
System.out.println(-1);
continue p;
}
//System.out.println(sum+" "+f);
ans+=d;
//return ;
}
System.out.println(ans);
}
}
public static double getDouble() throws Exception {
in.nextToken();
return in.nval;
}
public static String getString() throws Exception{
in.nextToken();
return in.sval;
}
public static int getInt() throws Exception{
in.nextToken();
return (int)in.nval;
}
}
class Edge{
int to,cap,cost,rev; //到达点,容量,消费,反向流量
public Edge(int a,int b,int c,int d) {
to=a;
cap=b;
cost=c;
rev=d;
}
}
class P implements Comparable{
int a,b;
public P(int a,int b) {
this.a=a;
this.b=b;
}
public int compareTo(Object o) {
P p=(P)o;
return this.a-p.a;
}
}