题目讲的是要从M个货源地提供K中商品个N个店主,不同的店主对不同商品的需求量不同,不同货源地K中商品的存货量也不同,第k种商品从货源地v到店主u的单位商品运输费用也不同,要求出满足所有店主要求的最小运输费用,若无法满足则输出“-1”。
我的想法是对于每一种商品分开处理, 每一种商品的运输费用都达到最小即可得到总费用最小,一个大循环for(i= 0; i < k; i++); 要求运输第i种商品满足所有店主的费用最小,其实就是求最小费用最大流的问题,将所有k种产品的最小费用加起来也就是总的最小费用了。题目的关键在于对第i种商品如何建图,该题目建成一个二分图,N个店主和M个货源地分为两个部分,可以增加一个超级源点s和一个超级汇点t,s有M条指向货源地的有向边,容量为货源地的存货量,费用为0,N和M个点之间的费用根据输入的val,容量为无穷大,然后N个店主各自有一条边指向汇点t,容量为该店主的需求量,费用为0,建图完成,接下来只需 求K次最小费用最大流就可,如果某一次求出的最大流不等于该中商品的需求量之和,则不满足条件,输出“-1”。
我的代码实现如下:
1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 using namespace std; 5 const int MAXN = 110; 6 const int INF = 0x7FFFFFFF; 7 int cap[MAXN][MAXN], cost[MAXN][MAXN]; 8 int path[MAXN], d[MAXN]; 9 int need[55][55], supply[55][55]; 10 bool inq[MAXN]; 11 int N, c, f; 12 queue<int> Q; 13 //求最小费用最大流 14 void Min_Cost(int s, int t) { 15 int i, u, v; 16 c = 0; f = 0; 17 while (1) { 18 memset(inq, 0, sizeof(inq)); 19 for (i = 0; i <= t; i++) d[i] = (i == s? 0 : INF); 20 Q.push(s); inq[s] = true; 21 while (!Q.empty()) { 22 u = Q.front(); Q.pop(); 23 inq[u] = false; 24 for (v = 0; v <= t; v++) { 25 if (cap[u][v] && d[v] > d[u] + cost[u][v]) { 26 d[v] = d[u] + cost[u][v]; 27 path[v] = u; 28 if (!inq[v]) { 29 inq[v] = true; 30 Q.push(v); 31 } 32 } 33 } 34 } 35 if (d[t] == INF) break; 36 int a = INF; 37 for (u = t; u != s; u = path[u]) a = (a < cap[path[u]][u]? a : cap[path[u]][u]); 38 for (u = t; u !=s; u = path[u]) { 39 cap[path[u]][u] -= a; 40 cap[u][path[u]] += a; 41 } 42 c += a * d[t]; 43 f += a; 44 } 45 } 46 47 int main() { 48 int i, j, u, v, n, m, k; 49 while (scanf("%d%d%d", &n, &m, &k), n != 0 || m != 0 || k != 0) { 50 N = n + m + 1; 51 int mincost = 0, val; 52 int s = 0, t = N, flag = 1; 53 for (i = 1; i <= n; i++) 54 for (j = 0; j < k; j++) 55 scanf("%d", &need[i][j]); 56 for (i = 1; i <= m; i++) 57 for (j = 0; j < k; j++) 58 scanf("%d", &supply[i][j]); 59 for (i = 0; i < k; i++) { 60 memset(cap, 0, sizeof(cap)); 61 memset(cost, 0, sizeof(cost)); 62 //建图过程 63 for (u = 1; u <= n; u++) { 64 for (v = 1; v <= m; v++) { 65 scanf("%d", &val); 66 cost[v][u+m] = val; 67 cost[u+m][v] = -val; 68 cap[v][u+m] = INF; 69 } 70 } 71 for (j = 1; j <= m; j++) { 72 cap[s][j] = supply[j][i]; 73 } 74 for (j = 1; j <= n; j++) { 75 cap[j+m][t] = need[j][i]; 76 } 77 78 if (flag) { 79 Min_Cost(s, t); 80 int count = 0; 81 for (j = 1; j <= n; j++) //求该中商品的总需求量 82 count += need[j][i]; 83 if (f != count) { //若不相等,则不满足 84 flag = 0; 85 } 86 mincost += c; 87 } 88 } 89 if (flag) 90 printf("%d\n", mincost); 91 else 92 printf("-1\n"); 93 } 94 return 0; 95 }
我的代码95行好长,,,第一次做最小费用最大流,出现错误希望大家指正~~