POJ 2516 Minimum Cost(最小费用最大流)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Tony5t4rk/article/details/81982343

文章地址:http://henuly.top/?p=801

Description:

Dearboy, a goods victualer, now comes to a big problem, and he needs your help. In his sale area there are N shopkeepers (marked from 1 to N) which stocks goods from him.Dearboy has M supply places (marked from 1 to M), each provides K different kinds of goods (marked from 1 to K). Once shopkeepers order goods, Dearboy should arrange which supply place provide how much amount of goods to shopkeepers to cut down the total cost of transport.

It’s known that the cost to transport one unit goods for different kinds from different supply places to different shopkeepers may be different. Given each supply places’ storage of K kinds of goods, N shopkeepers’ order of K kinds of goods and the cost to transport goods for different kinds from different supply places to different shopkeepers, you should tell how to arrange the goods supply to minimize the total cost of transport.

Input:

The input consists of multiple test cases. The first line of each test case contains three integers N, M, K (0 < N, M, K < 50), which are described above. The next N lines give the shopkeepers’ orders, with each line containing K integers (there integers are belong to [0, 3]), which represents the amount of goods each shopkeeper needs. The next M lines give the supply places’ storage, with each line containing K integers (there integers are also belong to [0, 3]), which represents the amount of goods stored in that supply place.

Then come K integer matrices (each with the size N * M), the integer (this integer is belong to (0, 100)) at the i-th row, j-th column in the k-th matrix represents the cost to transport one unit of k-th goods from the j-th supply place to the i-th shopkeeper.

The input is terminated with three “0”s. This test case should not be processed.

Output:

For each test case, if Dearboy can satisfy all the needs of all the shopkeepers, print in one line an integer, which is the minimum cost; otherwise just output “-1”.

Sample Input:

1 3 3
1 1 1
0 1 1
1 2 2
1 0 1
1 2 3
1 1 1
2 1 1

1 1 1
3
2
20

0 0 0

Sample Output:

4
-1

题目链接

有K个商品和由M个供应商提供给N家商店,不同个商品由不同的供应商提供给不同的商店消耗不同的费用,求满足所有商店的进货需求情况下的最小花费。

计算每种商品的供应总和和需求总和,若供不应求则输出-1(要把数据读完)。

在可以满足供需关系的情况下对每一件商品分别建图跑最小费用最大流最后求和。

建图:源点与商店之间建立一条流量为商店对此商品需求量,花费为0的边,汇点与供应商之间建立一条流量为供应商对此商品的供应量,花费为0的边,供应商与商店之间建立一条流量为无穷大费用为此供应商供应给此商店此商品的费用,跑最小费用最大流。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
const int INF = 0x3f3f3f3f;
const int maxn = 1e4 + 5;

struct Edge {
    int V, Next, Cap, Flow, Cost;
    Edge(int _V = 0, int _Next = 0, int _Cap = 0, int _Flow = 0, int _Cost = 0): V(_V), Next(_Next), Cap(_Cap), Flow(_Flow), Cost(_Cost) {}
};

int Head[maxn];
int Path[maxn];
int Dis[maxn];
bool Vis[maxn];
int Tot;
Edge edges[maxn << 4];

int N, M, K;
int Ans;
bool Flag;
int DemandSum;

void Init() {
    Tot = 0;
    memset(Head, -1, sizeof(Head));
}

void AddEdge(int U, int V, int Cap, int Cost) {
    edges[Tot].V = V;
    edges[Tot].Cap = Cap;
    edges[Tot].Cost = Cost;
    edges[Tot].Flow = 0;
    edges[Tot].Next = Head[U];
    Head[U] = Tot++;
    edges[Tot].V = U;
    edges[Tot].Cap = 0;
    edges[Tot].Cost = -Cost;
    edges[Tot].Flow = 0;
    edges[Tot].Next = Head[V];
    Head[V] = Tot++;
}

bool SPFA(int Start, int End) {
    memset(Dis, INF, sizeof(Dis));
    memset(Vis, false, sizeof(Vis));
    memset(Path, -1, sizeof(Path));
    Dis[Start] = 0;
    Vis[Start] = true;
    std::queue<int> Que;
    while (!Que.empty()) {
        Que.pop();
    }
    Que.push(Start);
    while (!Que.empty()) {
        int U = Que.front();
        Que.pop();
        Vis[U] = false;
        for (int i = Head[U]; i != -1; i = edges[i].Next) {
            int V = edges[i].V;
            if (edges[i].Cap > edges[i].Flow && Dis[V] > Dis[U] + edges[i].Cost) {
                Dis[V] = Dis[U] + edges[i].Cost;
                Path[V] = i;
                if (!Vis[V]) {
                    Vis[V] = true;
                    Que.push(V);
                }
            }
        }
    }
    return Path[End] != -1;
}

int MinCostMaxFlow(int Start, int End, int &MinCost) {
    int MaxFlow = 0;
    MinCost = 0;
    while (SPFA(Start, End)) {
        int Min = INF;
        for (int i = Path[End]; i != -1; i = Path[edges[i ^ 1].V]) {
            if (edges[i].Cap - edges[i].Flow < Min) {
                Min = edges[i].Cap - edges[i].Flow;
            }
        }
        for (int i = Path[End]; i != -1; i = Path[edges[i ^ 1].V]) {
            edges[i].Flow += Min;
            edges[i ^ 1].Flow -= Min;
            MinCost += edges[i].Cost * Min;
        }
        MaxFlow += Min;
    }
    return MaxFlow;
}

int main(int argc, char *argv[]) {
    while (~scanf("%d%d%d", &N, &M, &K) && (N + M + K)) {
        Flag = true;
        std::vector<std::vector<int> > Demand(N + 1);
        for (int i = 1; i <= N; ++i) {
            for (int j = 1, X; j <= K; ++j) {
                scanf("%d", &X);
                Demand[i].push_back(X);
            }
        }
        std::vector<std::vector<int> > Supply(M + 1);
        for (int i = 1; i <= M; ++i) {
            for (int j = 1, X; j <= K; ++j) {
                scanf("%d", &X);
                Supply[i].push_back(X);
            }
        }
        Ans = 0;
        for (int i = 1; i <= K; ++i) {
            Init();
            DemandSum = 0;
            for (int j = 1; j <= N; ++j) {
                AddEdge(0, j, Demand[j][i - 1], 0);
                DemandSum += Demand[j][i - 1];
                for (int k = 1, X; k <= M; ++k) {
                    scanf("%d", &X);
                    AddEdge(j, N + k, INF, X);
                    if (j == 1) {
                        AddEdge(N + k, N + M + 1, Supply[k][i - 1], 0);
                    }
                }
            }
            int TempCost, MaxFlow;
            MaxFlow = MinCostMaxFlow(0, N + M + 1, TempCost);
            if (MaxFlow != DemandSum) {
                Flag = false;
            }
            Ans += TempCost;
        }
        Ans = !Flag ? -1 : Ans;
        printf("%d\n", Ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Tony5t4rk/article/details/81982343