• POJ 2516 Minimum Cost (KM最优匹配)


    题意:有N家家店,每家店都对K种货物有需求;同时有M家仓库,对K钟货物有供应。对于每种货物,每个仓库送至每家店都有自己的单位费用。求满足所有店所有货物的最小费用

    分析:对于每一种货物,如果总需求大于总费用,那么无解的;否则可以用KM匹配求解每一种货物的最小费用。

    因为KM求的是最优匹配,所以建图的时候,建负权边即可。

    将每一份需求和每一份供应都离散化,而不是把一个店的需求和每个一仓库的供应建立边。

    #include<stdio.h>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const int maxn =305;
    const int INF= 1000000;
    
    int w[maxn][maxn];
    int m,n;//n左m右 
    int cx[maxn],cy[maxn];//顶标 
    bool usex[maxn],usey[maxn];//本回合使用的x,y 
    int link[maxn];//link[i]=x代表:在y图中的i与x相连 
    
    int A,B;
    
    bool dfs(int u){
        usex[u]=1;
        for(int i=1;i<=B;i++)
            if(!usey[i]&&cx[u]+cy[i]==w[u][i]){
                usey[i]=1;
                if(link[i]==-1||dfs(link[i])){ 
                    link[i]=u;
                    return 1;   
                }
            }
        return 0;
    }
    int KM(){
        memset(cy,0,sizeof(cy));
        memset(cx,-1,sizeof(cx));
        memset(link,-1,sizeof(link));
        for(int i=1;i<=A;i++)
            for(int j=1;j<=B;j++)
                cx[i]=max(cx[i],w[i][j]);
        for(int i=1;i<=A;i++){      
            while(1){
                int d=INF;
                memset(usex,0,sizeof(usex));
                memset(usey,0,sizeof(usey));
                if(dfs(i))break;
                for(int i=1;i<=A;i++)
                    if(usex[i])
                        for(int j=1;j<=B;j++)
                            if(!usey[j])d=min(d,cx[i]+cy[j]-w[i][j]);
                if(d==INF)return -1;
                for(int i=1;i<=A;i++)
                    if(usex[i])cx[i]-=d;
                for(int i=1;i<=B;i++)
                    if(usey[i])cy[i]+=d;
            }
        }
    
        int ans=0;
        for(int i=1;i<=B;i++){
            if(~link[i]){
                ans -= w[link[i]][i];
            }
        }
        return ans;
    }
    
    int nd[maxn][maxn];
    int sp[maxn][maxn];
    int ct[maxn][maxn][maxn];
    int cas;
    
    int cnt1[maxn],cnt2[maxn];
    
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        int T,tmp;
        int u,v,k;
        while(scanf("%d%d%d",&n,&m,&k)==3){
            if(!n && !m && !k) break;
            
            for(int i=1;i<=n;++i){
                for(int j=1;j<=k;++j){
                    scanf("%d",&nd[i][j]);
                }
            }
            
            for(int i=1;i<=m;++i){
                for(int j=1;j<=k;++j){
                    scanf("%d",&sp[i][j]);
                }
            }
            
            for(int i=1;i<=k;++i){
                for(int j=1;j<=n;++j){
                    for(int t = 1;t<=m;++t){
                        scanf("%d",&ct[i][j][t]);
                    }
                }
            }
    
            bool flag = true;
            for(int cas=1;cas<=k;++cas){
                int need = 0,supply =0;
                for(int i=1;i<=n;++i)   need += nd[i][cas];
                for(int i=1;i<=m;++i)   supply += sp[i][cas];
                if(need>supply){
                    flag = false;
                    break;
                }
            }
    
            if(!flag){
                puts("-1");
                continue;
            }
    
            int tot = 0;
            for(int cas = 1;cas<=k;++cas){
                A=B=0;
                for(int i=1;i<=n;++i){
                    for(int j=1;j<=nd[i][cas];++j){
                        cnt1[++A] = i;      
                    }
                }
                for(int i=1;i<=m;++i){
                    for(int j=1;j<=sp[i][cas];++j){
                        cnt2[++B] = i;
                    }
                }
                for(int i=1;i<=A;++i){
                    for(int j=1;j<=B;++j){
                        w[i][j] = -ct[cas][cnt1[i]][cnt2[j]];
                    }
                }
                int tmp = KM();
                tot+=tmp;
            }
            printf("%d
    ",tot);
        }
        return 0;
    }
    为了更好的明天
  • 相关阅读:
    Oracle-启动和关闭oracle的归档(ARCHIVELOG)模式
    Linux-数据表示方式
    Linux-21-30
    linux-1-10
    自律
    jenkins-修改系统时间
    jenkins-通过ssh username with private key配置节点服务器
    jenkins-slave开机自动启动
    mongodb-mongo使用
    mongodb-centos76yum安装mongodb
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9456893.html
Copyright © 2020-2023  润新知