zoukankan      html  css  js  c++  java
  • POJ2516 Minimum Cost【最小费用最大流】

    题意:

    有N个客户,M个仓库,和K种货物。已知每个客户需要每种货物的数量,每个仓库存储每种货物的数量,每个仓库运输各种货物去各个客户的单位费用。判断所有的仓库能否满足所有客户的需求,如果可以,求出最少的运输总费用。

    思路:

    最小费用最大流。先判断是否每种货物的存储总量都足够,足够的话,对每一种货物进行一次最小费用最大流求出完成这种货物运输的最小总费用,所有的总费用相加就是结果了。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    
    using namespace std;
    const int maxn = 110;
    const int inf = 99999999;
    
    int n, ans;
    int cap[maxn][maxn], pre[maxn];
    int cost[maxn][maxn], dis[maxn];
    int que[maxn];
    bool vis[maxn];
    
    bool spfa()
    {
        int i, head = 0, tail = 1;
        for(i = 0; i <= n; i ++){
            dis[i] = inf;
            vis[i] = false;
        }
        dis[0] = 0;
        que[0] = 0;
        while(tail != head){
            int u = que[head];
            vis[u] = true;
            for(i = 0; i <= n; i ++)
                if(cap[u][i] && dis[i] > dis[u] + cost[u][i]){
                    dis[i] = dis[u] + cost[u][i];
                    pre[i] = u;
                    if(!vis[i]){
                        vis[i] = true;
                        que[tail ++] = i;
                        if(tail == maxn) tail = 0;
                    }
                }
            vis[u] = false;
            head ++;
            if(head == maxn) head = 0;
        }
        if(dis[n] == inf) return false;
        return true;
    }
    
    void end()
    {
        int i, sum = inf;
        for(i = n; i != 0; i = pre[i])
            sum = min(sum, cap[pre[i]][i]);
        for(i = n; i != 0; i = pre[i]){
            cap[pre[i]][i] -= sum;
            cap[i][pre[i]] += sum;
            ans += cost[pre[i]][i] * sum;
        }
    }
    
    int main()
    {
        int N, M, K, i, j, k;
        int need[maxn][maxn], NeedK[maxn];
        int have[maxn][maxn], HaveK[maxn];
        while(cin>>N>>M>>K,N,M,K)
        {
            memset(NeedK, 0, sizeof(NeedK));
            for(i = 1; i <= N; i ++)
                for(j = 1; j <= K; j ++){
                    scanf("%d", &need[i][j]);    //  第i个客户需要第j种货物的量。
                    NeedK[j] += need[i][j];      //  第j种货物总共需要的量。
                }
            memset(HaveK, 0, sizeof(HaveK));
            for(i = 1; i <= M; i ++)
                for(j = 1; j <= K; j ++){
                    scanf("%d", &have[i][j]);    //  第i个仓库存储第j种货物的量。
                    HaveK[j] += have[i][j];      //  第j种货物总共需要的量。
                }
            bool flag = true;
            for(i = 1; i <= K; i ++)             //  判断所有货物是否足够。
                if(NeedK[i] > HaveK[i]){
                    flag = false; break;
                }
            ans = 0;
            n = N + M + 1;
            for(k = 1; k <= K; k ++){
                memset(cap, 0, sizeof(cap));
                for(i = 1; i <= N; i ++)         //  建图。
                    for(j = 1; j <= M; j ++){
                        scanf("%d", &cost[j][M+i]);
                        cost[M+i][j] = -cost[j][M+i];
                        cap[j][M+i] = inf;
                    }
                if(!flag) continue;
                for(i = 1; i <= M; i ++){
                    cap[0][i] = have[i][k];
                    cost[0][i] = cost[i][0] = 0;
                }
                for(i = 1; i <= N; i ++){
                    cap[M+i][n] = need[i][k];
                    cost[M+i][n] = cost[n][M+i] = 0;
                }
                while(spfa()) end();            //  最小费用最大流算法。
            }
            if(flag) cout << ans << endl;
            else cout << -1 << endl;
        }
        return 0;
    }
  • 相关阅读:
    C++面向对象三大特性
    4G通信技术LTE介绍
    汉澳战斗檄文,跟着汉澳去战斗
    AdapterView及其子类之二:使用ListActivity及ArrayAdapter创建列表
    [置顶] Objective-C ,ios,iphone开发基础:protocol 协议(委托,代理)的声明
    C语言中几种类型所占字节数
    UART, SPI, IIC的详解及三者的区别和联系
    数学基础详解 2——概率论与数理统计
    1—机器学习简介
    Python基础(11)——反射、异常处理
  • 原文地址:https://www.cnblogs.com/darklights/p/7643013.html
Copyright © 2011-2022 走看看