这题的大意是有N个店主,有M个供应商,对于N个店主,每个主有一定的需求量(对应着K种商品),M个供应商也对应着一定的供应量。然后相应的供应是有一定的费用。最后问说是否能满足需求,不满足的话输出-1,满足的话输出最小的费用。模型是比较裸,这里对于每个商品,都建个图来费用流,相应的建个超级源点和超级汇点。每次spfa去找,复杂度是O(V*E*E)。
感谢:
http://www.cppblog.com/Icyflame/archive/2009/06/30/88891.html
代码
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
const int MAX = 55;
const int INF = INT_MAX;
int N, M, K;
int need[MAX][MAX];
int give[MAX][MAX];
int move[MAX][MAX][MAX];
int SS, TT;
int mm[2 * MAX][2 * MAX]; //flow map
int cc[2 * MAX][2 * MAX]; //cost map
int prev[2 * MAX];
int flow[2 * MAX];
int dis[2 * MAX];
int in[2 * MAX];
void ready()
{
for(int i = 1; i <= N; i++) for(int j = 1; j <= K; j++) scanf("%d", &need[i][j]);
for(int i = 1; i <= M; i++) for(int j = 1; j <= K; j++) scanf("%d", &give[i][j]);
for(int k = 1; k <= K; k++) for(int i = 1; i <= N; i++) for(int j = 1; j <= M; j++) scanf("%d", &move[k][i][j]);
}
void makeMap(int kind)
{
SS = 0, TT = N + M + 1;
//make the flow map
memset(mm, 0, sizeof(mm));
for(int i = 1; i <= N; i++) mm[SS][i] = need[i][kind];
for(int i = 1; i <= M; i++) mm[i + N][TT] = give[i][kind];
for(int i = 1; i <= N; i++) for(int j = 1; j <= M; j++) mm[i][j + N] = need[i][kind];
//make the cost map
memset(cc, 0, sizeof(cc));
for(int i = 1; i <= N; i++) for(int j = 1; j <= M; j++)
{
cc[i][j + N] = move[kind][i][j];
cc[j + N][i] = -move[kind][i][j];
}
}
int spfa()
{
memset(in, 0, sizeof(in));
memset(dis, -1, sizeof(dis));
memset(prev, -1, sizeof(prev));
memset(flow, 0, sizeof(flow));
in[SS] = 1, dis[SS] = 0, flow[SS] = INF;
vector<int> v;
v.push_back(SS);
for(int i = 0; i < v.size(); i++)
{
int u = v[i];
in[u] = 0;
for(int j = SS; j <= TT; j++)
{
if(mm[u][j] > 0 && (dis[j] == -1 || dis[u] + cc[u][j] < dis[j]))
{
dis[j] = dis[u] + cc[u][j];
//in[j] = 1;
prev[j] = u;
flow[j] = min(flow[u], mm[u][j]);
if(in[j] == 0) in[j] = 1, v.push_back(j);
}
}
}
return flow[TT];
}
int mcmf()
{
int res = 0;
while(1)
{
int now = spfa();
if(now == 0) break;
int u = TT;
while(u != SS)
{
int v = prev[u];
mm[v][u] -= now;
mm[u][v] += now;
res += now * cc[v][u];
u = v;
}
}
for(int i = 1; i <= N; i++)
{
if(mm[SS][i] > 0) return -1;
}
return res;
}
int main()
{
while(scanf("%d%d%d", &N, &M, &K), N)
{
int res = 0;
ready();
for(int k = 1; k <= K; k++)
{
makeMap(k);
int t = mcmf();
if(t == -1)
{
res = -1;
break;
}
res += t;
}
printf("%d\n", res);
}
}