最小费用最大流初探。过程极为简单:把边作为边权,然后找超级源点和超级汇点之间的最短路,如果有最短路,则对它增广。
http://blog.csdn.net/lin375691011/article/details/18923267
这是lin的博客,讲得(网络流的概念)比较详细。这个题的细节都在代码中了,就不再叙述了。
#include <iostream> #include <algorithm> #include <queue> using namespace std; #define M 105 #define inf 1 << 30 int capacity_need[M][M], capacity_have[M][M], construction_cost[M][M][M], n, m, k; int capacity[M][M]; int flow[M][M]; int weight[M][M]; int shortestdistances[M]; int pre_node[M]; bool visited[M]; /** * insearch for shortest path from SuperSource[0], to SuperSink[n+m+1]; * * @return whether there are shortest paths */ bool spfa() { for (int i = 0; i <= n + m + 1; i++) { shortestdistances[i] = inf; pre_node[i] = -1; visited[i] = false; } shortestdistances[0] = 0; visited[0] = true; queue <int> q; q.push(0); while (!q.empty()) { int t = q.front(); q.pop(); visited[t] = false; for (int i = 1; i <= n + m + 1; i++) { if (capacity[t][i] > flow[t][i] && shortestdistances[i] > shortestdistances[t] + weight[t][i]) { shortestdistances[i] = shortestdistances[t] + weight[t][i]; pre_node[i] = t; if (!visited[i]) { q.push(i); visited[i] = true; } } } } if (pre_node[n + m + 1] == -1) { return false; } return true; } /** * get maxflow */ void getMaxflow() { //if there is the shortest path, find the key edge that controls the flow, then change the flow while (spfa()) { int maxflow = inf; int p = n + m + 1; while (pre_node[p] != -1) { //find maxflow = min(maxflow, capacity[pre_node[p]][p] - flow[pre_node[p]][p]); // from p'pre to p, the real flow equals to the capacity - flow_now p = pre_node[p]; } p = n + m + 1; while (pre_node[p] != -1) { //change flow[pre_node[p]][p] += maxflow; flow[p][pre_node[p]] = -flow[pre_node[p]][p]; p = pre_node[p]; } } } int main() { int i, j, d, ans; while (cin >> n >> m >> k, n || m || k) { ans = 0; bool flag = false; for (i = 1; i <= n; i++) { for (j = 1; j <= k; j++) { cin >> capacity_need[i][j]; } } for (i = 1; i <= m; i++) { for (j = 1; j <= k; j++) { cin >> capacity_have[i][j]; } } for (i = 1; i <= k; i++) { for (j = 1; j <= n; j++) { for (d = 1; d <= m; d++) { cin >> construction_cost[i][d][j]; } } } for (i = 1; i <= k; i++) { memset(capacity, 0, sizeof(capacity)); memset(flow, 0, sizeof(flow)); memset(weight, 0, sizeof(weight)); for (j = 1; j <= m; j++) { capacity[0][j] = capacity_have[j][i]; //SuperSource's capacity should be the capacity current have(dust) } for (j = 1; j <= n; j++) { capacity[m + j][m + n + 1] = capacity_need[j][i]; //SuperSink's capacity should be the capacity current need(store) } for (j = 1; j <= m; j++) { for (d = 1; d <= n; d++) { capacity[j][d + m] = capacity_have[j][i]; //Dust to store should be the dust's capacity } } for (j = 1; j <= m; j++) { for (d = 1; d <= n; d++) { weight[j][d + m] = construction_cost[i][j][d]; weight[d + m][j] = -construction_cost[i][j][d]; // MINUS FOR REMAINING FLOW NOW } } getMaxflow(); for (j = 1; j <= n; j++) { if (capacity[j + m][n + m + 1] != flow[j + m][n + m + 1]) { // support != requirement flag = true; break; } } if (flag) { break; } for (j = 1; j <= m; j++) { for (d = 1; d <= n; d++) { ans += flow[j][d + m] * weight[j][d + m]; //CLEARLY RIGHT } } } if (flag) { cout << -1 << endl; } else { cout << ans << endl; } } }