Loading

POJ 2516:Minimum Cost(最小费用流)

https://vjudge.net/problem/11079/origin

题意:有N个商店和M个供应商和K种物品,每个商店每种物品有一个需求数,每个供应商每种物品有一个供应量,供应商到商店之间的运输需要花费,如果供不应求输出-1,否则输出最小花费。

思路:比较明显的最小费用流。想法大概都是源点和供应商连一条容量为供应量,花费为0的边,商店和汇点之间连一条容量为需求量,花费为0的边,供应商和商店之间连一条容量为INF,花费为题意给出的花费的边。建图的话一开始是直接对于每一个商店每一种物品和每一个供应商每一种物品都看做一个点,这样的点数是n*k+m*k+两个源点,超级大的图,就TLE了。看了下别人的思路,每一种商品是独立的,那么对于每一种商品建一次图,这样的点数是n + m + 两个源点,然后跑 k 次。优化了N多。。。。太菜鸡了。。。。还有数组开的不能太小,开55的时候TLE,105就AC了。

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <cstring>
  5 #include <string>
  6 #include <cmath>
  7 #include <queue>
  8 #include <vector>
  9 #include <map>
 10 #include <set>
 11 using namespace std;
 12 #define INF 0x3f3f3f3f
 13 #define N 105
 14 typedef long long LL;
 15 struct Edge {
 16     int u, v, cap, cost;
 17     Edge () {}
 18     Edge (int u, int v, int cap, int cost) : u(u), v(v), cap(cap), cost(cost) {}
 19 } edge[N*N];
 20 int tot, pre[N], vis[N], dis[N], S, T;
 21 int shop[N][N], sup[N][N], tolshop[N], tolsup[N], cost[N][N][N];
 22 vector<int> G[N];
 23 void Add(int u, int v, int cap, int cost) {
 24     edge[tot] = Edge(u, v, cap, cost);
 25     G[u].push_back(tot++);
 26     edge[tot] = Edge(v, u, 0, -cost);
 27     G[v].push_back(tot++);
 28 }
 29 
 30 int SPFA() {
 31     queue<int> que;
 32 //    puts("SPFA");
 33     memset(dis, INF, sizeof(dis));
 34     memset(vis, 0, sizeof(vis));
 35     dis[S] = 0; que.push(S);
 36     vis[S] = 1;
 37     while(!que.empty()) {
 38         int u = que.front(); que.pop();
 39         vis[u] = 0;
 40         for(int i = 0; i < G[u].size(); i++) {
 41             Edge& e = edge[G[u][i]];
 42             if(dis[u] + e.cost < dis[e.v] && e.cap > 0) { // 先松弛在判断是否在队里
 43                 dis[e.v] = dis[u] + e.cost;
 44                 pre[e.v] = G[u][i];
 45                 if(vis[e.v]) continue;
 46                 que.push(e.v);
 47                 vis[e.v] = 1;
 48             }
 49         }
 50     }
 51     return dis[T] < INF;
 52 }
 53 
 54 void MFMC(int &maxflow, int &cost) {
 55     int u = T, flow = INF;
 56     while(u != S) {
 57         Edge& e = edge[pre[u]];
 58         if(e.cap < flow) flow = e.cap;
 59         u = e.u;
 60     } u = T;
 61     while(u != S) {
 62         Edge& e1 = edge[pre[u]];
 63         Edge& e2 = edge[pre[u]^1];
 64         e1.cap -= flow; e2.cap += flow;
 65         cost += flow * e1.cost;
 66         u = e1.u;
 67     }
 68     maxflow += flow;
 69 }
 70 
 71 int main() {
 72     int n, m, k;
 73     while(~scanf("%d%d%d", &n, &m, &k), n + m + k) {
 74         S = 0; T = n + m + 1;
 75         memset(tolsup, 0, sizeof(tolsup));
 76         memset(tolshop, 0, sizeof(tolshop));
 77         for(int i = 1; i <= n; i++) {
 78             for(int j = 1; j <= k; j++) {
 79                 scanf("%d", &shop[i][j]);
 80                 tolshop[j] += shop[i][j];
 81             }
 82         }
 83         for(int i = 1; i <= m; i++) {
 84             for(int j = 1; j <= k; j++) {
 85                 scanf("%d", &sup[i][j]);
 86                 tolsup[j] += sup[i][j];
 87             }
 88         }
 89         for(int x = 1; x <= k; x++) {
 90             for(int i = 1; i <= n; i++) {
 91                 for(int j = 1; j <= m; j++) {
 92                     scanf("%d", &cost[x][i][j]);
 93                 }
 94             }
 95         }
 96         int flag = 1;
 97         int maxflow = 0, mincost = 0;
 98         for(int x = 1; x <= k; x++) {
 99             if(tolshop[x] > tolsup[x]) {
100                 flag = 0; break;
101             }
102             tot = 0;
103             for(int i = S; i <= T; i++) G[i].clear();
104             for(int i = 1; i <= n; i++) {
105                 Add(i, T, shop[i][x], 0);
106             }
107             for(int i = 1; i <= m; i++) {
108                 Add(S, i + n, sup[i][x], 0);
109             }
110             for(int i = 1; i <= n; i++) {
111                 for(int j = 1; j <= m; j++) {
112                     Add(j + n, i, sup[j][x], cost[x][i][j]);
113                 }
114             }
115             while(SPFA()) MFMC(maxflow, mincost);
116         }
117         if(flag) printf("%d\n", mincost);
118         else puts("-1");
119     }
120     return 0;
121 }

 

posted @ 2016-12-30 01:42  Shadowdsp  阅读(466)  评论(0编辑  收藏  举报