POJ-2516 Minimum Cost

Posted on 2021-12-05 16:41  Capterlliar  阅读(16)  评论(0编辑  收藏  举报

题意:有k种商品,m家供货商,n位顾客。给出每家供货商每种商品的货源,每位顾客对每种商品的需求,每种商品在每对供给中的运费,求每位顾客的要求都能满足时的最小运费。如果无法满足顾客要求,输出-1.

解:对每种商品跑最小费用最大流,然后加上每次的最小费用。如果最大流比顾客需求小,输出-1。建立源点,流向供给商,边权为货源数量;供给商向每位顾客连边,边权为货源数量和运费;顾客向聚点连边,边权为需求,然后跑板子。板子因为inf大小不一样,调了好久。

代码:

  1 #include <stdio.h>
  2 #include <algorithm>
  3 #include <queue>
  4 using namespace std;
  5 #define maxx 1000005
  6 #define maxm 100005
  7 #define maxn 5005
  8 #define inf 0x3f3f3f3f
  9 #define ll long long
 10 int n,m,k;
 11 int a[55][55],b[55][55],c[55][55][55];
 12 
 13 int head[maxn],cnt;
 14 struct Edge{
 15     int v,w,next,flow;
 16 }edge[maxm];
 17 int s,t;
 18 int dis[maxn],incf[maxn],pre[maxn],inque[maxn];
 19 int maxflow,mincost;
 20 void init(){
 21     memset(head,-1,sizeof(head));
 22     maxflow=mincost=0;
 23     cnt=0;
 24 }
 25 void add(int u,int v,int flow,int cost){
 26     edge[cnt].w=cost;
 27     edge[cnt].v=v;
 28     edge[cnt].flow=flow;
 29     edge[cnt].next=head[u];
 30     head[u]=cnt++;
 31 }
 32 void addEdge(int u,int v,int flow,int cost){
 33     add(u,v,flow,cost);
 34     add(v,u,0,-cost);
 35 }
 36 int spfa(){
 37     queue<int>q;
 38     memset(dis,0x3f,sizeof(dis));
 39     memset(inque,0,sizeof(inque));
 40     q.push(s); dis[s]=0; inque[s]=1; incf[s]=inf;
 41     while(!q.empty()){
 42         int u=q.front();q.pop();
 43         inque[u]=0;
 44         for(int i=head[u];~i;i=edge[i].next){
 45             if(!edge[i].flow)    continue;
 46             int v=edge[i].v;
 47             if(dis[v]>dis[u]+edge[i].w){
 48                 dis[v]=dis[u]+edge[i].w;
 49                 incf[v]=min(incf[u],edge[i].flow);
 50                 pre[v]=i;
 51                 if(!inque[v]){
 52                     q.push(v);
 53                     inque[v]=1;
 54                 }
 55             }
 56         }
 57     }
 58     if(dis[t]==inf)
 59         return 0;
 60     return 1;
 61 }
 62 void MCMF(){
 63     while(spfa()){
 64         int x=t;
 65         maxflow+=incf[t];
 66         mincost+=dis[t]*incf[t];
 67         int i;
 68         while(x!=s){
 69             i=pre[x];
 70             edge[i].flow-=incf[t];
 71             edge[i^1].flow+=incf[t];
 72             x=edge[i^1].v;
 73         }
 74     }
 75 }
 76 
 77 signed main(){
 78     while(~scanf("%d%d%d",&n,&m,&k)) {
 79         if(n==0&&m==0&&k==0)
 80             break;
 81         s=n+m+5,t=s+1;
 82         for(int i=1;i<=n;i++)
 83             for(int j=1;j<=k;j++)
 84                 scanf("%d",&a[i][j]);
 85         for(int i=1;i<=m;i++)
 86             for(int j=1;j<=k;j++)
 87                 scanf("%d",&b[i][j]);
 88         for(int l=1;l<=k;l++)
 89             for(int i=1;i<=n;i++)
 90                 for(int j=1;j<=m;j++)
 91                     scanf("%d",&c[l][i][j]);
 92         int ans=0;
 93         for(int l=1;l<=k;l++){
 94             int need=0;
 95             init();
 96             for(int i=1;i<=n;i++)
 97                 addEdge(i,t,a[i][l],0),need+=a[i][l];
 98             for(int i=1;i<=m;i++)
 99                 addEdge(s,i+n,b[i][l],0);
100             for(int i=1;i<=n;i++)
101                 for(int j=1;j<=m;j++)
102                     addEdge(j+n,i,b[j][l],c[l][i][j]);
103             MCMF();
104             if(maxflow<need){
105                 ans=-1;
106                 break;
107             }
108             else
109                 ans+=mincost;
110         }
111         printf("%d\n",ans);
112     }
113     return 0;
114 }
View Code