pku 2561 Minimum Cost 最小费用最大流
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; }