Minimum Cost POJ

来源:互联网 发布:网络运维 英文缩写 编辑:程序博客网 时间:2024/06/07 06:35

传送门:POJ2516

题意:有n个客户,k种商品,m个仓库,每个仓库里都存有不等量的k种商品,现给出i种商品运送到客户j的单位花费,问满足所有客户需求的最小花费是多少,若不能满足需求则输出-1。

思路:典型最小费用流,并且能否满足需求是可以提前算出来的,只要k种物品中的每一种都总需求小于总供应(即供大于求)就能满足。然后是建图,我们无法一下求出k种物品的最小花费,但由于k种物品是互不相干的,我们可以分开求然后加和,对于每种物品来看就成了最基本的费用流问题,建图跑就行了。

代码:

#include<stdio.h>#include<iostream>#include<algorithm>#include<queue>#include<string.h>#define ll long long#define inf 0x3f3f3f3fusing namespace std;const int MAXN=110;const int MAXM=10100;int head[MAXN],pre[MAXN],dis[MAXN],book[MAXN];int cnt=0,N,n,m;//NΪµãÊý struct node{int to,next,cap,flow,cost;}edge[MAXM];void init(){cnt=0;memset(head,-1,sizeof(head));}void addedge(int u,int v,int cap,int cost){edge[cnt].to=v;edge[cnt].cap=cap;edge[cnt].flow=0;edge[cnt].cost=cost;edge[cnt].next=head[u];head[u]=cnt++;edge[cnt].to=u;edge[cnt].cap=0;edge[cnt].flow=0;edge[cnt].cost=-cost;edge[cnt].next=head[v];head[v]=cnt++;}bool spfa(int s,int t){queue<int>q;while(!q.empty())q.pop();for(int i=0;i<=N;i++){dis[i]=inf;pre[i]=-1;book[i]=0;}dis[s]=0;book[s]=1;q.push(s);while(!q.empty()){int u=q.front();q.pop();book[u]=0;for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;if(edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost){dis[v]=dis[u]+edge[i].cost;pre[v]=i;if(!book[v]){book[v]=1;q.push(v);}} } }return pre[t]!=-1;}int min_cost_max_flow(int s,int t,int &cost){int flow=0;while(spfa(s,t)){int temp=inf;for(int i=pre[t];i!=-1;i=pre[edge[i^1].to])temp=min(temp,edge[i].cap-edge[i].flow);for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){edge[i].flow+=temp;edge[i^1].flow-=temp;cost+=edge[i].cost*temp;}flow+=temp;}return flow;}int shop[55][55],supply[55][55],w[55][55];bool check(int k){for(int x=1;x<=k;x++){int sum=0,sum1=0;for(int i=1;i<=n;i++)sum+=shop[i][x];for(int i=1;i<=m;i++)sum1+=supply[i][x];if(sum>sum1)return true;}return false;}void build(int x){init();for(int i=1;i<=m;i++)addedge(0,i,supply[i][x],0);for(int i=1;i<=n;i++)addedge(m+i,n+m+1,shop[i][x],0);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){addedge(j,m+i,inf,w[i][j]);}}int main(){int k,t;while(cin>>n>>m>>k){if(n+m+k==0)break;int sum=0;int source=0,sink=N=m+n+1;for(int i=1;i<=n;i++)for(int j=1;j<=k;j++)scanf("%d",&shop[i][j]),sum+=shop[i][j];for(int i=1;i<=m;i++)for(int j=1;j<=k;j++)scanf("%d",&supply[i][j]);if(check(k)){for(int x=1;x<=k;x++)for(int i=0;i<n;i++)for(int j=0;j<m;j++)scanf("%d",&t);cout<<-1<<endl;continue;}int cost=0,flow=0;for(int x=1;x<=k;x++){for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&w[i][j]);build(x);flow+=min_cost_max_flow(source,sink,cost);}//cout<<flow<<endl;if(flow<sum)cout<<-1<<endl;elsecout<<cost<<endl;}}


原创粉丝点击