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;
    }
  • 相关阅读:
    Mongodb 利用mongoshell进行数据类型转换
    利用Cordova开发移动应用程序
    mongodb Capped Collections 固定集合
    ubuntu desktop使用中遇到的问题
    php session 锁机制和基本安全设置
    mongodb update
    mongodb query
    mongodb Insert 、 remove 、操作原子性(atomicity)
    mongodb index(索引)
    mongodb笔记 getting started
  • 原文地址:https://www.cnblogs.com/darklights/p/7643013.html
Copyright © 2011-2022 走看看