POJ 2516 Minimum Cost(最小费用最大流)
来源:互联网 发布:男朋友接吻会硬 知乎 编辑:程序博客网 时间:2024/06/07 09:44
POJ 2516 Minimum Cost(最小费用最大流)
http://poj.org/problem?id=2516
题意:
给出n个客户对k种商品的需求量,又给出m个仓库对k种物品的存货量以及对k种物品从i仓库到j客户的一个物品的运费价格,让判断是否可以满足客户需求,然后就是如果满足求出最小的运费.
分析:
首先我们必须判断m个仓库是否有足够的k种商品给n个客户,如果不足,那么明显就是不行的. 下面假设仓库的商品足够的话:
对于每一种商品我们都算出满足满足顾客需求量的最小运费即可.所以我们对K种商品分开处理如下,假设当前处理第x种商品,建图如下:
源点s编号0, m个仓库编号1到m, n个顾客编号m+1到m+n, 汇点编号m+n+1.
从源点s到每个仓库i有边(s, i, 仓库i对商品x的存货量, 0)
从每个仓库i到顾客j有边(i, j, INF, 仓库i到顾客j的单位X商品的运费)
从每个顾客j到汇点t有边(j, t, 顾客j对X商品的需求量, 0)
然后我们求最小费用最大流即可求出N个顾客对第X种商品的最小运费.
AC代码:
#include<cstdio>#include<cstring>#include<queue>#include<algorithm>#include<vector>#define INF 1e9using namespace std;const int maxn=200+10;struct Edge{ int from,to,cap,flow,cost; Edge(){} Edge(int f,int t,int c,int fl,int co):from(f),to(t),cap(c),flow(fl),cost(co){}};struct MCMF{ int n,m,s,t; vector<Edge> edges; vector<int> G[maxn]; bool inq[maxn]; int d[maxn]; int p[maxn]; int a[maxn]; void init(int n,int s,int t) { this->n=n, this->s=s, this->t=t; edges.clear(); for(int i=0;i<n;++i) G[i].clear(); } void AddEdge(int from,int to,int cap,int cost) { edges.push_back(Edge(from,to,cap,0,cost)); edges.push_back(Edge(to,from,0,0,-cost)); m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BellmanFord(int &flow, int &cost) { for(int i=0;i<n;++i) d[i]=INF; memset(inq,0,sizeof(inq)); d[s]=0, a[s]=INF, inq[s]=true, p[s]=0; queue<int> Q; Q.push(s); while(!Q.empty()) { int u=Q.front(); Q.pop(); inq[u]=false; for(int i=0;i<G[u].size();++i) { Edge &e=edges[G[u][i]]; if(e.cap>e.flow && d[e.to]>d[u]+e.cost) { d[e.to]= d[u]+e.cost; p[e.to]=G[u][i]; a[e.to]= min(a[u],e.cap-e.flow); if(!inq[e.to]){ Q.push(e.to); inq[e.to]=true; } } } } if(d[t]==INF) return false; flow +=a[t]; cost +=a[t]*d[t]; int u=t; while(u!=s) { edges[p[u]].flow += a[t]; edges[p[u]^1].flow -=a[t]; u = edges[p[u]].from; } return true; } int Min_cost() { int flow=0,cost=0; while(BellmanFord(flow,cost)); return cost; }}MM;int n,m,k;int need[50+5][50+5]; //need[i][j]表i顾客对j商品的需求量int have[50+5][50+5]; //have[i][j]表i仓库对j商品的提供量int cost[50+5][50+5][50+5]; //cost[x][i][j] 表j仓库到i顾客对x商品的单位运费int main(){ while(scanf("%d%d%d",&n,&m,&k)==3 && n) { //n客户数量 m商家数量 k商品种类 int goods[maxn];//货物需求量,用来判断货物是否足够 //对于j种商品需要的数量 int enough=true;//初始货物充足 memset(goods,0,sizeof(goods)); for(int i=1;i<=n;++i) for(int j=1;j<=k;++j) { scanf("%d",&need[i][j]); goods[j]+= need[i][j]; } for(int i=1;i<=m;++i) for(int j=1;j<=k;++j) { scanf("%d",&have[i][j]); goods[j] -=have[i][j]; } for(int h=1;h<=k;++h) for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) scanf("%d",&cost[h][i][j]); for(int i=1;i<=k;++i)if(goods[i]>0)//货物不足,不用计算了{enough=false;break;} if(!enough)//初始货物不足 { printf("-1\n"); continue; } int min_cost=0; for(int g=1;g<=k;++g) { int src=0, dst=n+m+1; MM.init(n+m+2,src,dst); for(int i=1;i<=m;++i) MM.AddEdge(src,i,have[i][g],0); for(int i=1;i<=n;++i) MM.AddEdge(m+i,dst,need[i][g],0); for(int i=1;i<=m;++i) for(int j=1;j<=n;++j) { MM.AddEdge(i,j+m,INF,cost[g][j][i]); } min_cost += MM.Min_cost(); } printf("%d\n",min_cost); } return 0;}
阅读全文
0 0
- POJ 2516 Minimum Cost 【MCMF:最小费用最大流】
- POJ 2516 Minimum Cost 最小费用最大流
- POJ 2516 Minimum Cost (最小费用最大流,KM解法)
- poj 2516 Minimum Cost--最小费用最大流
- poj-2516-Minimum Cost-最小费用最大流
- POJ 2516 Minimum Cost (最小费用最大流)
- poj 2516 Minimum Cost(最小费用最大流)
- poj 2516 Minimum Cost (最小费用最大流)
- POJ 2516 Minimum Cost 最小费用最大流
- poj 2516 Minimum Cost(最小费用最大流)
- POJ--2516--Minimum Cost【最小费用最大流】
- POJ 2516 Minimum Cost(最小费用最大流)
- poj 2516Minimum Cost 最小费用最大流
- poj 2516 Minimum Cost 最小费用最大流
- POJ 2516 Minimum Cost(最小费用最大流)
- POJ 2516 Minimum Cost (最小费用最大流)
- poj 2516 Minimum Cost 【最小费用最大流】
- 【最小费用最大流】POJ-2516 Minimum Cost
- 押韵令3
- 2705: [SDOI2012]Longge的问题
- 编程之美——寻找数组中最大的K个数
- Binder连接池
- HDOJ 1258 Sum It Up(DFS)
- POJ 2516 Minimum Cost(最小费用最大流)
- ble连接之后onServicesDiscovered 不被调用
- MyBatis 入门开发 ----输入,输出参数
- 顺序表-改(移动)
- 浅谈sql中的in与not in,exists与not exists的区别以及性能分析
- 2017杭电多校第七场1008 Hard challenge(级角排序)HDU 6127
- CSS 浮动规则
- 程序员高效编程的14点建议
- 列表、列表解析、过滤器filter和map