http://poj.org/problem?id=2516
刚接触,所以这道题目整了一天的时间,囧!!
题意描述也很难理解:n个店主,要从Dearboy的m个仓库里进k中商品。首先给出n个店主对k种的商品的需求量,然后给出Dearboy的m个仓库中分别存放k中货物的数量。最后给出的是从m个仓库输送k种商品到n个店主的费用。
由以上约束条件建立约束图,利用mcmf算法求解。。。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define maxn 107
using namespace std;
const int inf = 99999999;
int sto[maxn][maxn],need[maxn][maxn],cost[maxn][maxn][maxn];
int pre[maxn],f[maxn][maxn],c[maxn][maxn],w[maxn][maxn];
int dis[maxn];
bool inq[maxn];
int n,m,k,s,t;
void input()
{
int i,j,l;
//输入n个店主的需求
for (i = 1; i <= n; ++i)
for (j = 1; j <= k; ++j) scanf("%d",&need[i][j]);
//输入m个仓库存储的k中商品的数量
for (i = 1; i <= m; ++i)
for (j = 1; j <= k; ++j) scanf("%d",&sto[i][j]);
//输入运输的花费
for (l = 1; l <= k; ++l)
for (i = 1; i <= n; ++i)
for (j = 1; j <= m; ++j) scanf("%d",&cost[l][i][j]);
}
void init()
{
memset(f,0,sizeof(f));
memset(c,0,sizeof(c));
}
void spfa(int s)
{
int v;
queue<int>q;
dis[s] = 0;
q.push(s); inq[s] = true;
while (!q.empty())
{
int u = q.front(); q.pop();
inq[u] = false;
for (v = 0; v <= t; ++v)
{
if (c[u][v] > f[u][v] && dis[v] > dis[u] + w[u][v])
{
dis[v] = dis[u] + w[u][v];
pre[v] = u;
if (!inq[v])
{
inq[v] = true;
q.push(v);
}
}
}
}
}
void mcmf(int s)
{
int i;
while (1)
{
for (i = 0; i < maxn; ++i)
{
dis[i] = inf; inq[i] = false;
pre[i] = -1;
}
spfa(s);
if (pre[t] == -1) break;
int x = t,minf = inf;
while (pre[x] != -1)
{
minf = min(minf,c[pre[x]][x] - f[pre[x]][x]);
x = pre[x];
}
x = t;
while (pre[x] != -1)
{
f[pre[x]][x] += minf;
f[x][pre[x]] += minf;
x = pre[x];
}
}
}
int main()
{
int i,j,l;
while (~scanf("%d%d%d",&n,&m,&k))
{
if (!n && !m && !k) break;
input();
s = 0; t = n + m + 1;
bool flag = false;
int ans = 0;
//对每一种商品求最小费用最大流
for (l = 1; l <= k && !flag; ++l)
{
//建图
init();
for (i = 1; i <= m; ++i) c[s][i] = sto[i][l];
for (i = 1; i <= n; ++i) c[i + m][t] = need[i][l];
for (i = 1; i <= m; ++i)
for (j = 1; j <= n; ++j) c[i][j + m] = sto[i][l];
for (i = 1; i <= m; ++i)
{
for (j = 1; j <= n; ++j)
{
w[i][j + m] = cost[l][j][i];
w[j + m][i] = -w[i][j + m];
}
}
mcmf(s);
//判断是否可行
for (i = 1; i <= n; ++i)
{
if (c[i + m][t] != f[i + m][t])
{
flag = true; break;
}
}
for (i = 1; i <= m; ++i)
{
for (j = 1; j <= n; ++j)
{
ans += w[i][j + m]*f[i][j + m];
}
}
}
if (flag) puts("-1");
else printf("%d\n",ans);
}
return 0;
}