• poj21516


    首先对于一种商品

    如果这种货不足需求就直接输出-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
    ",ans);  
        }  
        return 0;  
    }    
  • 相关阅读:
    e552. 取Applet的参数
    e551. 精简的Applet
    e558. 在Applet中多图片交互显示
    e1087. try/catch语句
    e1086. if/else语句
    e1087. 用For循环做数组的遍历
    e1084. 捕获错误和异常
    Zookeeper 应用程序
    Zookeeper API
    Java并发编程:volatile关键字解析
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8304261.html
Copyright © 2020-2023  润新知