Poj 2516 Minimum Cost (最小花费最大流)

题目链接:

  Poj  2516  Minimum Cost

题目描述:

  有n个商店,m个仓储,每个商店和仓库都有k种货物。嘛!现在n个商店要开始向m个仓库发出订单了,订单信息为当前商店对每种货物的需求量。不同的商店从不同的仓库购买不同货物花费不同,问是不是能满足所有商店的要求,如果能商店花费总和最小为多少?

解题思路:

  简单的费用流,要跑K次最小花费最大流,每次只对一种货物建图跑费用流。每次建图以0为源点, [1,m]为仓库, [m+1, n+m]为商店, n+m+1为汇点。0与[1,m]连边,边容量为仓库存货,边单位流量的花费为0。

[1,m]与[m+1,n+m]连边,边容量为INF,边单位流量的花费为对应仓库供应i货物给对应商店的单位花费。[m+1,n+m]与汇点连边,边容量为商店需求,边单位流量的花费为0。这个题目建图时候的初始化一定要搞好,不然很容易TLE。

  1 #include <queue>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6 using namespace std;
  7 
  8 const int maxn = 210;
  9 const int INF = 0x3f3f3f3f;
 10 int flow[maxn][maxn], cap[maxn][maxn];
 11 int shop[maxn][maxn], supply[maxn][maxn];
 12 int vis[maxn], pre[maxn], dis[maxn], cost[maxn][maxn];
 13 int c, Flow, s, e;
 14 
 15 bool spfa ()
 16 {
 17     queue <int> Q;
 18     for (int i=s; i<=e; i++)
 19     {
 20         dis[i] = INF;
 21         vis[i] = 0;
 22     }
 23     dis[0] = 0;
 24     vis[0] = 1;
 25     Q.push (s);
 26     while (!Q.empty())
 27     {
 28         int u = Q.front();
 29         Q.pop();
 30         vis[u] = 0;
 31         for (int v=s; v<=e; v++)
 32         {
 33             if (cap[u][v]>flow[u][v] && dis[v]>dis[u]+cost[u][v])
 34             {
 35                 dis[v] = dis[u] + cost[u][v];
 36                 pre[v] = u;
 37                 if (!vis[v])
 38                 {
 39                     vis[v] = 1;
 40                     Q.push(v);
 41                 }
 42             }
 43         }
 44     }
 45     if (dis[e] == INF)
 46         return false;
 47     return true;
 48 }
 49 
 50 void MincostMaxflow ()
 51 {
 52     memset (flow, 0, sizeof(flow));
 53     c = Flow = 0;
 54     while (spfa())
 55     {
 56         int Min = INF;
 57         for (int i=e; i!=s; i=pre[i])
 58             Min = min (Min, cap[pre[i]][i]-flow[pre[i]][i]);
 59         for (int i=e; i!=s; i=pre[i])
 60         {
 61             flow[pre[i]][i] += Min;
 62             flow[i][pre[i]] -= Min;
 63         }
 64         Flow += Min;
 65         c += Min * dis[e];
 66     }
 67 }
 68 
 69 int main ()
 70 {
 71     int n, m, k;
 72     while (scanf ("%d %d %d", &n, &m, &k), n||m||k)
 73     {
 74         int flag, Cost;
 75         flag = Cost = s = 0, e = n + m + 1;
 76         
 77         for (int i=1; i<=n; i++)
 78             for (int j=1; j<=k; j++)
 79                 scanf ("%d", &shop[i][j]);
 80 
 81         for (int i=1; i<=m; i++)
 82             for (int j=1; j<=k; j++)
 83                 scanf ("%d", &supply[i][j]);
 84                 
 85         memset (cap, 0, sizeof(cap));
 86         memset (cost, 0, sizeof(cost));
 87         for (int i=1; i<=m; i++)
 88             for (int j=m+1; j<=n+m; j++)
 89                 cap[i][j] = INF;
 90 
 91         for (int i=1; i<=k; i++)
 92         {
 93             int total = 0;
 94             for (int j=1; j<=n; j++)
 95                 for (int l=1; l<=m; l++)
 96                 {
 97                     scanf ("%d", &cost[l][j+m]);
 98                     cost[j+m][l] = -cost[l][j+m];
 99                 }
100                 
101             if (flag)
102                 continue;
103 
104             for (int j=1; j<=n; j++)
105                 {
106                     cap[j+m][e] = shop[j][i];
107                     total += shop[j][i];
108                 }
109             for (int j=1; j<=m; j++)
110                 cap[s][j] = supply[j][i];
111 
112             MincostMaxflow();
113             if (Flow < total)
114                 flag = 1;
115             Cost += c;
116             
117         }
118         printf ("%d\n", flag?-1:Cost);
119     }
120     return 0;
121 }
posted @ 2015-08-19 20:43  罗茜  阅读(235)  评论(0编辑  收藏  举报