zoukankan      html  css  js  c++  java
  • POJ 2516 Minimum Cost(拆点+KM完备匹配)

    题目链接:http://poj.org/problem?id=2516

    题目大意:

    第一行是N,M,K

    接下来N行:第i行有K个数字表示第i个卖场对K种商品的需求情况

    接下来M行:第j行有K个数字表示第j个库房对K种商品的存货情况

    接下来K个N*M的矩阵:

    每个矩阵(i,j)表示第k种商品从第j个库房运到第i个卖场的运费(单价)

    求满足所有需求的最小花费,如果不能全部满足输出-1。

    解题思路:

    拆点,对于第k种商品有:

    把每个卖场的需求按件数拆成各个小点(比如需要x件就看做x个点)

    把每个库房的存货量按件数拆成各个小点(同上)

    然后以运费为权值连边(单向边)

    做K次完备匹配即可。

    代码:

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cstring>
      6 using namespace std;
      7 const int N=55;
      8 const int M=205;
      9 const int INF=0x3f3f3f3f;
     10 
     11 int nx,ny,d;
     12 int offer[N][N],need[N][N],cost[N][N][N];//cost[k][i][j]表示将第k件物品从供应商j送到老板i的花费
     13 int lx[M],ly[M],link[M],g[M][M],belongA[M],belongB[M];
     14 bool visx[M],visy[M];
     15 
     16 bool dfs(int x){
     17     visx[x]=true;
     18     for(int y=0;y<ny;y++){
     19         if(visy[y]||!g[x][y]) continue;
     20         int tmp=lx[x]+ly[y]-g[x][y];
     21         if(tmp==0){
     22             visy[y]=true;
     23             if(link[y]==-1||dfs(link[y])){
     24                 link[y]=x;
     25                 return true;
     26             }
     27         }
     28         else d=min(d,tmp);
     29     }
     30     return false;
     31 }
     32 
     33 int KM(){
     34     memset(link,-1,sizeof(link));
     35     memset(ly,0,sizeof(ly));
     36     for(int i=0;i<nx;i++){
     37         lx[i]=-INF;
     38         for(int j=0;j<ny;j++){
     39             if(g[i][j]>lx[i])
     40                 lx[i]=g[i][j];
     41         }
     42     }
     43     for(int x=0;x<nx;x++){
     44         while(true){
     45             memset(visx,false,sizeof(visx));
     46             memset(visy,false,sizeof(visy));
     47             d=INF;
     48             if(dfs(x)) break;
     49             for(int i=0;i<nx;i++){
     50                 if(visx[i])
     51                     lx[i]-=d;
     52             }
     53             for(int i=0;i<ny;i++){
     54                 if(visy[i])
     55                     ly[i]+=d;
     56             }
     57         }
     58     }
     59     int ans=0;
     60     for(int i=0;i<ny;i++){
     61         if(link[i]!=-1){
     62             ans+=g[link[i]][i];
     63         }
     64     }
     65     return ans;
     66 }
     67 
     68 int main(){
     69     int n,m,k;
     70     while(~scanf("%d%d%d",&n,&m,&k)){
     71         if(n==0&&m==0&&k==0) break;
     72         for(int i=0;i<n;i++){
     73             for(int j=0;j<k;j++){
     74                 scanf("%d",&need[i][j]);
     75             }
     76         }
     77         for(int i=0;i<m;i++){
     78             for(int j=0;j<k;j++){
     79                 scanf("%d",&offer[i][j]);
     80             }
     81         }
     82         for(int t=0;t<k;t++){
     83             for(int i=0;i<n;i++){
     84                 for(int j=0;j<m;j++)
     85                     scanf("%d",&cost[t][i][j]);
     86             }
     87         }
     88         bool flag=true;
     89         //首先对于一种商品,如果这种所有的存货不足需求就直接输出-1
     90         for(int t=0;t<k;t++){
     91             int sum1=0,sum2=0;
     92             for(int i=0;i<n;i++){
     93                 sum1+=need[i][t];
     94             }
     95             for(int i=0;i<m;i++){
     96                 sum2+=offer[i][t];
     97             }
     98             if(sum1>sum2){
     99                 flag=false;
    100                 break;
    101             }
    102         }
    103         if(!flag){
    104             puts("-1");
    105             continue;
    106         }
    107         int ans=0;
    108         for(int t=0;t<k;t++){
    109             int cntA=0,cntB=0;
    110             //拆点,
    111             for(int i=0;i<n;i++){
    112                 for(int j=0;j<need[i][t];j++){
    113                     belongA[cntA++]=i;
    114                 }
    115             }
    116             for(int i=0;i<m;i++){
    117                 for(int j=0;j<offer[i][t];j++){
    118                     belongB[cntB++]=i;
    119                 }
    120             }
    121             for(int i=0;i<cntA;i++){
    122                 for(int j=0;j<cntB;j++){
    123                     g[i][j]=-cost[t][belongA[i]][belongB[j]];
    124                 }
    125             }
    126             nx=cntA,ny=cntB;
    127             ans+=KM();
    128         }
    129         printf("%d
    ",-ans);
    130     }
    131     return 0;
    132 }
  • 相关阅读:
    循环神经网络(Recurrent Neural Network)
    特征选择
    程序猿能挣多少钱
    python socket
    python 2 encode and decode
    pandas series
    source collection list
    pep8摘要
    python 正则表达式
    django显示图片
  • 原文地址:https://www.cnblogs.com/fu3638/p/8785738.html
Copyright © 2011-2022 走看看