POJ 2516 - Minimum Cost 分为几次做最小费用最大流...

              题意:

                       有N个零售商..有M个仓库...有K种物品要卖...现在告诉每个零售商对每种商品的需求量..每个仓库对每种商品的存储量..以及每个仓库买每种商品到零售商的价格(一次性..不是单价..理解为距离更和谐...)..问最少要花费多少使得N个零售商都满足需求...

              题解:

                        构图很简单了...但要注意的是.. TLE...解决方法是分k次做..


Program:

#include<iostream>  
#include<algorithm>  
#include<stdio.h>  
#include<string.h>  
#include<math.h>  
#include<queue>  
#define MAXN 8005
#define MAXM 8000005  
#define oo 1000000007  
#define ll long long  
using namespace std;    
struct MCMF    
{    
       struct node    
       {    
              int x,y,c,v,next;     
       }line[MAXM];    
       int Lnum,_next[MAXN],pre[MAXN],dis[MAXN],flow,cost;    
       bool inqueue[MAXN];    
       void initial(int n)    
       {    
              Lnum=-1;    
              for (int i=0;i<=n;i++) _next[i]=-1;    
       }    
       void addline(int x,int y,int c,int v)    
       {    
              line[++Lnum].next=_next[x],_next[x]=Lnum;    
              line[Lnum].x=x,line[Lnum].y=y,line[Lnum].c=c,line[Lnum].v=v;    
              line[++Lnum].next=_next[y],_next[y]=Lnum;    
              line[Lnum].x=y,line[Lnum].y=x,line[Lnum].c=0,line[Lnum].v=-v;    
       }    
       bool SPFA(int s,int e)    
       {    
              int x,k,y;    
              queue<int> Q;    
              while (!Q.empty()) Q.pop();    
              memset(dis,0x7f,sizeof(dis));    
              memset(inqueue,false,sizeof(inqueue));    
              Q.push(s);    
              dis[s]=0,pre[s]=-1;    
              while (!Q.empty())    
              {    
                      x=Q.front(),Q.pop(),inqueue[x]=false;    
                      for (k=_next[x];k!=-1;k=line[k].next)      
                         if (line[k].c)    
                         {    
                               y=line[k].y;    
                               if (dis[y]>dis[x]+line[k].v)    
                               {    
                                        dis[y]=dis[x]+line[k].v;    
                                        pre[y]=k;    
                                        if (!inqueue[y])    
                                        {    
                                                inqueue[y]=true;    
                                                Q.push(y);    
                                        }    
                               }    
                         }    
              }    
              if (dis[e]>oo) return false;    
              flow=oo,cost=0;    
              for (k=pre[e];k!=-1;k=pre[line[k].x])     
                  flow=min(flow,line[k].c),cost+=line[k].v;        
              cost*=flow;    
              for (k=pre[e];k!=-1;k=pre[line[k].x])    
                  line[k].c-=flow,line[k^1].c+=flow;      
              return true;    
       }    
       void MinCostMaxFlow(int s,int e,int &Aflow,int &Acost)    
       {    
              Aflow=0,Acost=0;    
              while (SPFA(s,e))    
              {    
                     Aflow+=flow;    
                     Acost+=cost;     
              }         
       }    
}T;
int A[55][55],B[55][55],dis[55][55][55];
int main() 
{                
      int Af,Ac,ansc,sum,s,e,x,t,i,j,n,m,k;  
      while (~scanf("%d%d%d",&n,&m,&k) && n)
      { 
              for (i=1;i<=n;i++) 
                  for (t=1;t<=k;t++)
                     scanf("%d",&A[t][i]);
              for (i=1;i<=m;i++) 
                  for (t=1;t<=k;t++)
                     scanf("%d",&B[t][i]); 
              for (t=1;t<=k;t++)
                 for (i=1;i<=n;i++)
                   for (j=1;j<=m;j++)
                     scanf("%d",&dis[t][i][j]);
              ansc=0;
              for (t=1;t<=k;t++)
              {
                      s=(n+m)+3,e=s+1,T.initial(e),sum=0;
                      for (i=1;i<=n;i++) T.addline(s,i,A[t][i],0),sum+=A[t][i];
                      for (i=1;i<=m;i++) T.addline(i+n,e,B[t][i],0);
                      for (i=1;i<=n;i++)
                         for (j=1;j<=m;j++)
                            T.addline(i,j+n,oo,dis[t][i][j]);
                      T.MinCostMaxFlow(s,e,Af,Ac);
                      if (Af!=sum) break;
                      ansc+=Ac;
              }
              if (t<=k) printf("-1\n");
                   else printf("%d\n",ansc);
      }
      return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值