Minimum Cost POJ - 2516(模板题。。没啥好说的。。)
题意:
从发货地到商家 送货 求送货花费的最小费用。。。
有m个发货地,,,n个商家,,每个商家所需要的物品和物品的个数都不一样,,,每个发货地有的物品和物品的个数也不一样,,,
从不同的发货地到不同的商家 送不同的物品 所花费的价钱 也不一样。。
解析;
建立超级源s和超级汇t
因为每个商家所需的每个物品的数量都不一样,,,所以我们要分物品来进行最小费用最大流
在最外面一个循环,遍历每一个物品,,,然后对于当前物品建图
把每个发货地和s连边 权值为每个发货地所拥有的当前物品的数量,,,花费0
把商家个t连边,, 权值为每个商家所需要的当前物品的数量,,花费0
然后 发货地和商家连边。。。权值为INF, 花费为每个发货地到每个商家对于当前物品所对应的花费
这是一个对象所需不同物品的个数不一样的题
贴一个对象所需不同物品的个数一样的题:https://www.cnblogs.com/WTSRUVF/p/9202751.html
代码如下:
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <algorithm> #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; const int maxn = 100100, INF = 0x7fffffff; typedef long long LL; int head[maxn], d[maxn], vis[maxn], p[maxn], f[maxn]; int frome[maxn], to[maxn], ca[55][55][55]; int needs[55][55], have[55][55]; int n, m, s, t, k; int cnt, flow, value; struct node{ int u, v, c, w, next; }Node[maxn]; void add_(int u, int v, int c, int w) { Node[cnt].u = u; Node[cnt].v = v; Node[cnt].c = c; Node[cnt].w = w; Node[cnt].next = head[u]; head[u] = cnt++; } void add(int u, int v, int c, int w) { add_(u, v, c, w); add_(v, u, 0 ,-w); } int spfa() { queue<int> Q; for(int i=0; i<maxn; i++) d[i] = INF; mem(vis, 0); mem(p, -1); Q.push(s); d[s] = 0; vis[s] = 1; p[s] = 0; f[s] = INF; while(!Q.empty()) { int u = Q.front(); Q.pop(); vis[u] = 0; for(int i=head[u]; i!=-1; i=Node[i].next) { node e = Node[i]; if(d[e.v] > d[e.u] + e.w && e.c > 0) { d[e.v] = d[e.u] + e.w; p[e.v] = i; f[e.v] = min(f[u], e.c); if(!vis[e.v]) { Q.push(e.v); vis[e.v] = 1; } } } } if(p[t] == -1) return 0; flow += f[t]; value += f[t]* d[t]; for(int i=t; i!=s; i=Node[p[i]].u) { Node[p[i]].c -= f[t]; Node[p[i]^1].c += f[t]; } return 1; } int max_flow() { value = 0; flow = 0; while(spfa()); return value; } int main() { while(~scanf("%d%d%d",&n,&m,&k) && n+m+k) { int ret = 0; int ok = 1; s = 0, t = (n+m)*2+10; mem(head, -1); mem(frome, 0); mem(to, 0); cnt = 0; for(int i=1; i<=n; i++) for(int j=1; j<=k; j++) { scanf("%d",&needs[i][j]); frome[j] += needs[i][j]; } for(int i=1; i<=m; i++) for(int j=1; j<=k; j++) { scanf("%d",&have[i][j]); to[j] += have[i][j]; } for(int i=1; i<=k; i++) for(int j=1; j<=n; j++) for(int l=1; l<=m; l++) scanf("%d",&ca[i][j][l]); for(int i=1; i<=k; i++) { if(frome[i] > to[i]) { printf("-1\n"); ok = 0; break; } } if(!ok) continue; for(int i=1; i<=k; i++) { mem(head, -1); cnt = 0; for(int j=1; j<=n; j++) add(j, t, needs[j][i], 0); for(int j=1; j<=m; j++) add(s, n+j, have[j][i], 0); for(int j=1; j<=m; j++) for(int l=1; l<=n; l++) add(n+j, l, INF, ca[i][l][j]); ret += max_flow(); } cout<< ret <<endl; } return 0; }
自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。