题目链接:
题目描述:
有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 ", flag?-1:Cost); 119 } 120 return 0; 121 }