• 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 }
  • 相关阅读:
    Smart Client Architecture and Design Guide
    Duwamish密码分析篇, Part 3
    庆贺发文100篇
    .Net Distributed Application Design Guide
    New Introduction to ASP.NET 2.0 Web Parts Framework
    SPS toplevel Site Collection Administrators and Owners
    来自Ingo Rammer先生的Email关于《Advanced .Net Remoting》
    The newsletter published by Ingo Rammer
    深度探索.Net Remoting基础架构
    信道、接收器、接收链和信道接受提供程序
  • 原文地址:https://www.cnblogs.com/fu3638/p/8785738.html
Copyright © 2020-2023  润新知