首先对于一种商品

如果这种货不足需求就直接输出-1

剩下的就是KM算法

分k次分别计算每种商品的最小权值匹配

代码:

#include<cstdio>  
#include<cstring>  
#include<algorithm>  
#include<cmath>  
using namespace std;  
int n,m,k,shop[55][55],sup[55][55],cost[55][55][55],edges[200][200],cntA,cntB;  
int belongA[200],belongB[200],A[200],B[200],visA[200],visB[200],mat[200],d;  
int dfs(int i) 
{  
    visA[i]=1;  
    for (int j=1;j<=cntB;j++) 
     if (!visB[j]&&edges[i][j])
      {  
        int t=edges[i][j]-A[i]-B[j];  
        if (!t)
         {  
            visB[j]=1;  
            if (!mat[j]||dfs(mat[j]))
              {  
                mat[j]=i;  
                return 1;  
             }  
         }
        else d=min(d,t);  
      }    
    return 0;  
}  
int match()
{  
    memset(A,0x3f,sizeof(A));  
    memset(B,0,sizeof(B));  
    for (int i=1;i<=cntA;i++)  
     for (int j=1;j<=cntB;j++)A[i]=min(A[i],edges[i][j]);  
    memset(mat,0,sizeof(mat));  
    for (int i=1;i<=cntA;i++)
     {  
        while (1)
         {  
            memset(visA,0,sizeof(visA));  
            memset(visB,0,sizeof(visB));  
            d=1e9;  
            if (dfs(i))break;  
            for (int j=1;j<=cntA;j++)  
             if (visA[j]) A[j]+=d;  
            for (int j=1;j<=cntB;j++)  
             if (visB[j]) B[j]-=d;  
         }  
     }  
    int ans=0;  
    for (int i=1;i<=cntB;i++)ans+=edges[mat[i]][i];  
    return ans;  
}  
int main()
{  
    while (~scanf("%d%d%d",&n,&m,&k),n+m+k)
     {  
        for (int i=1;i<=n;i++)  
         for (int j=1;j<=k;j++)scanf("%d",&shop[i][j]);  
        for (int i=1;i<=m;i++)  
         for (int j=1;j<=k;j++)scanf("%d",&sup[i][j]);  
        for (int t=1;t<=k;t++)  
         for (int i=1;i<=n;i++)  
          for (int j=1;j<=m;j++)scanf("%d",&cost[t][i][j]);  
        int flag=1;  
        for (int i=1;i<=k;i++)
         {  
            int need=0,have=0;  
            for (int j=1;j<=n;j++)need+=shop[j][i];  
            for (int j=1;j<=m;j++)have+=sup[j][i];  
            if (need>have) 
             {  
                flag=0;  
                puts("-1");  
                break;  
             }  
         }  
        if (!flag)continue;  
        int ans=0;  
        for (int t=1;t<=k;t++)
         {  
            cntA=cntB=0;  
            for (int i=1;i<=n;i++)  
             for (int j=1;j<=shop[i][t];j++)belongA[++cntA]=i;  
            for (int i=1;i<=m;i++)  
             for (int j=1;j<=sup[i][t];j++)belongB[++cntB]=i;  
            for (int i=1;i<=cntA;i++)  
             for (int j=1;j<=cntB;j++)  
              edges[i][j]=cost[t][belongA[i]][belongB[j]];  
            ans+=match();  
         }   
        printf("%d\n",ans);  
    }  
    return 0;  
}    

 

posted on 2018-01-17 17:58  宣毅鸣  阅读(89)  评论(0编辑  收藏  举报