代码改变世界

Poj2516 最小费用最大流

2013-08-08 23:14  凝月流风  阅读(589)  评论(0编辑  收藏  举报

题目讲的是要从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行好长,,,第一次做最小费用最大流,出现错误希望大家指正~~