Time Limit: 4000MS | Memory Limit: 65536K | |
Total Submissions: 19883 | Accepted: 7055 |
Description
Input
Output
Sample Input
1 3 3 1 1 1 0 1 1 1 2 2 1 0 1 1 2 3 1 1 1 2 1 1 1 1 1 3 2 20 0 0 0
Sample Output
4 -1
Source
都在代码里了,不不建议抄袭代码,代码里有些调试代码,有需要的可以看代码之前注释,前面是解释,精髓在最后三行。
1 /* 2 本题心得:一开始做题就有种感觉需要对商品拆点,然后满足每个商人,但是这样的话每个商品要拆为n个点,必然会有很大的空间浪费造成tle, 3 实在没思路之后看了博客,看到说每种商品都是独立的,意思就是把商人需要的每种物品都单独买,然后统计最后结果就行了,这里有一个细节就是, 4 因为目的是满足所有商人情况下的最小费用,那也就是最小费用最大流,所以我们事先判断某种商品是否够用,如果够用,那么最大流一定是满载的, 5 所以不必担心找不到最大流,就找最小花费就行了。 6 对于每个商品,我们记得要清空head数组,额贼,这个把我坑了好久,后来想如果不清空必然会在spfa中造成无限循环(想想为什么?),所以对每件 7 商品都需要init,对于每件商品,我们建立超级源点指向那些供应商,容量为最大供应数目花费为0,对于每个商人,我们建立一条边指向超级汇点,容量为商人 8 对这件商品的需求数目(限制每个商人得到的物品数),花费为0,对于每个供应商和他的商人之间建立一条由供应商指向商人的边,cap为inf(由于前面我们已经限制了每个供应商可以提供的物品) 9 花费为这个供应商对这个商人供应这件物品的cost,跑一波费用流就ojk了。 10 这样我们就 11 通过供应商 -> 商人 限制了价格 12 通过 s -> 供应商 限制了供应个数 13 通过商人 -> t 限制了商人的需求数目。 14 */ 15 #include <cstdio> 16 #include <cstring> 17 #include <algorithm> 18 #include <queue> 19 using namespace std; 20 21 const int maxn = 50 + 5, maxm = 1e4 + 5, inf = 0x3f3f3f3f; 22 int want[maxn][maxn], supply[maxn][maxn], sumwant[maxn], sumsupply[maxn], costij[maxn][maxn][maxn]; 23 struct Edge { 24 int to, next, cap, flow, cost, from; 25 } edge[maxm]; 26 int head[maxn << 1], tot; 27 int pre[maxn << 1], dis[maxn << 1]; 28 bool vis[maxn << 1]; 29 30 int N; 31 32 void init(int n) { 33 N = n; 34 tot = 0; 35 memset(head, -1, sizeof head); 36 } 37 38 void addedge(int u, int v, int cap, int cost) { 39 edge[tot].to = v; edge[tot].cap = cap; edge[tot].cost = cost; edge[tot].flow = 0; edge[tot].from = u; 40 edge[tot].next = head[u]; head[u] = tot ++; 41 edge[tot].to = u; edge[tot].cap = 0; edge[tot].cost = -cost; edge[tot].flow = 0; edge[tot].from = v; 42 edge[tot].next = head[v]; head[v] = tot ++; 43 } 44 45 bool spfa(int s, int t) { 46 queue <int> que; 47 // memset(dis, inf, sizeof dis); 48 // memset(vis, false, sizeof vis); 49 // memset(pre, -1, sizeof pre); 50 for(int i = 0; i <= N; i ++) { 51 dis[i] = inf; 52 vis[i] = false; 53 pre[i] = -1; 54 } 55 dis[s] = 0; 56 vis[s] = true; 57 que.push(s); 58 while(!que.empty()) { 59 // printf("in bfs"); 60 int u = que.front(); 61 que.pop(); 62 vis[u] = false; 63 for(int i = head[u]; ~i; i = edge[i].next) { 64 int v = edge[i].to; 65 if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost) { 66 dis[v] = dis[u] + edge[i].cost; 67 pre[v] = i; 68 if(!vis[v]) { 69 vis[v] = true; 70 // printf("now in push of bfs"); 71 que.push(v); 72 } 73 } 74 } 75 } 76 return ~pre[t]; 77 // if(pre[t] == -1) return false; 78 // else return true; 79 } 80 81 int mincostmaxflow(int s, int t) { 82 int cost = 0; 83 while(spfa(s, t)) { 84 // printf("spfa is true"); 85 int Min = inf; 86 for(int i = pre[t]; ~i; i = pre[edge[i ^ 1].to]) { 87 if(Min > edge[i].cap - edge[i].flow) 88 Min = edge[i].cap - edge[i].flow; 89 // printf("now is find min"); 90 } 91 for(int i = pre[t]; ~i; i = pre[edge[i ^ 1].to]) { 92 edge[i].flow += Min; 93 edge[i ^ 1].flow -= Min; 94 cost += edge[i].cost * Min; 95 // printf("now is update"); 96 } 97 } 98 return cost; 99 } 100 101 int main() { 102 int n, m, k; 103 while(~scanf("%d %d %d", &n, &m, &k) && (n | m | k)) { 104 105 memset(want, 0, sizeof want); 106 memset(supply, 0, sizeof supply); 107 memset(sumwant, 0, sizeof sumwant); 108 memset(sumsupply, 0, sizeof sumsupply); 109 for(int i = 1; i <= n; i ++) { 110 for(int j = 1; j <= k; j ++) { 111 scanf("%d", &want[i][j]); 112 sumwant[j] += want[i][j]; 113 } 114 } 115 for(int i = 1; i <= m; i ++) { 116 for(int j = 1; j <= k; j ++) { 117 scanf("%d", &supply[i][j]); 118 sumsupply[j] += supply[i][j]; 119 } 120 } 121 bool flag = true; 122 for(int i = 1; i <= k; i ++) { 123 if(sumwant[i] > sumsupply[i]) { 124 flag = false; 125 break; 126 } 127 } 128 for(int q = 1; q <= k; q ++) { 129 for(int i = 1; i <= n; i ++) { 130 for(int j = 1; j <= m; j ++) { 131 scanf("%d", &costij[q][i][j]);//第q件物品,第i个人从第j个供应商的花费 132 } 133 } 134 } 135 int s = 0, t = m + n + 1, mcmf = 0; 136 if(flag) { 137 for(int q = 1; q <= k; q ++) { 138 init(n + m + 2); 139 // printf("***************\n"); 140 for(int i = 1; i <= m; i ++) { 141 addedge(s, i, supply[i][q], 0); 142 } 143 for(int i = 1; i <= n; i ++) { 144 addedge(i + m, t, want[i][q], 0); 145 } 146 for(int i = 1; i <= n; i ++) { 147 for(int j = 1; j <= m; j ++) { 148 addedge(j, i + m, inf, costij[q][i][j]); 149 } 150 } 151 // for(int i = 0; i < tot; i ++) { 152 // printf("%d -> %d\n", edge[i].from, edge[i].to); 153 // } 154 mcmf += mincostmaxflow(s, t); 155 } 156 printf("%d\n", mcmf); 157 } else printf("-1\n"); 158 } 159 return 0; 160 }
原文:https://www.cnblogs.com/bianjunting/p/11399210.html