最小费.
主要是这题有K种货物搞得关系很复杂, 开始建图卡住, 其实把k种货物分开来建k次图跑k次就好了.
然后判断最大流和是否满足需求, 若满足则输出最小费和, 若不满足, 则输出-1.
貌似还可以用KM
代码:
//最小费用流
// 建k次图... 最小费
#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN = 200;
const int MAXM = 40005;
const int INF = 1<<30;
int mincost,maxflow;
int n,m;
int U[MAXM],V[MAXM],cap[MAXM],flow[MAXM],cost[MAXM],next[MAXM];
int head[MAXN],pre[MAXN],Edge[MAXN],dis[MAXN];
int num;
void addEdge(int u,int v,int Cap,int Cost)
{
flow[num] = flow[num+1] = 0;
V[num] = v;
U[num] = u;
cap[num] = Cap;
cost[num] = Cost;
next[num] = head[u];
head[u] = num++;
V[num] = u;
U[num] = v;
cap[num] = 0;
cost[num] = -Cost;
next[num] = head[v];
head[v] = num++;
}
void MCMF(int st,int ed)
{
queue<int> q;
memset(flow,0,sizeof(flow));
mincost = maxflow = 0;
for(;;)
{
bool inq[MAXN];
for(int i = st;i <= ed;++i) dis[i] = (i == st ? 0 : INF);
memset(inq,0,sizeof(inq));
q.push(st);
while(!q.empty())
{
int u = q.front(); q.pop();
inq[u] = 0;
for(int e = head[u];e != -1;e = next[e])
{
if(cap[e] > flow[e] && dis[u] + cost[e] < dis[V[e]])
{
dis[V[e]] = dis[u] + cost[e];
pre[V[e]] = U[e];
Edge[V[e]] = e;
if(!inq[V[e]])
{
q.push(V[e]);
inq[V[e]] = 1;
}
}
}
}//SPFA增广
if(dis[ed] == INF) break;
int delta = INF;//delta为可改进量
for(int u = ed;u != st;u = pre[u])
delta = min(delta,cap[Edge[u]] - flow[Edge[u]]);//遍历最短路径的边,并修改可改进量
for(int u = ed;u != st;u = pre[u])
{
flow[Edge[u]] += delta;//更新正向流量
flow[Edge[u] ^ 1] -= delta;//通过异或1取得反向边的序号,并更新反向流量
}
mincost += dis[ed] * delta;
maxflow += delta;
}
}
int sell[52][52];
int buy[52][52];
int value[52][52][52];
int main()
{
// buildGraphs
int K;
while(scanf("%d%d%d", &n, &m, &K) == 3)
{
if(!n && !m && !K) break;
int need = 0;
int totflow = 0;
int totcost = 0;
for(int i=0; i<n; i++)
for(int k=0; k<K; k++)
{
scanf("%d", &buy[k][i]); //n个买家
need+=buy[k][i];
}
for(int i=0; i<m; i++)
for(int k=0; k<K; k++)
{
scanf("%d", &sell[k][i]); //m个仓库
}
for(int k=0; k<K; k++)
for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
{
scanf("%d", &value[k][i][j]); //j->i
}
for(int k=0; k<K; k++)
{
num = 0;
memset(head,-1,sizeof(head)); // 0 卖 1~m 买 m+1~m+n 汇 m+n+1
for(int i=0; i<m; i++)
{
addEdge(0,i+1,sell[k][i],0);
}
for(int i=0; i<n; i++)
{
addEdge(i+1+m, m+n+1, buy[k][i], 0);
}
for(int i=0; i<n; i++)
for(int j=0; j<m; j++) //卖
{
addEdge(j+1, i+1+m, INF, value[k][i][j]);
}
//MCMF
MCMF(0,n+m+1);
totcost += mincost;
totflow += maxflow;
//printf("%d\n",mincost);
}
if(totflow!=need) totcost = -1;
printf("%d\n", totcost);
}
}