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 }