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

http://poj.org/problem?id=2516

题意:

有N的商店,M个仓库,k件商品,每个商店对于商品都有不同的数量需求,而仓库也存有不同的商品,每个仓库运送每个商品都有一个花费,问满足每个商家不最小费是多少

思路:

数据条件有点多,可以对每一种商品都进行一次最大流最小费,把每次的花费加起来,就可解了。
注意如果仓库的商品数量不够商家的需求,那么输出为-1,特判一下即可

#include <iostream>
#include <string.h>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <stdio.h>
#include <deque>

using namespace std;

#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define maxn 100005
#define eps 0.00000001
#define PI acos(-1.0)
#define M 1000000007

struct Edge{
    int v, w, cap, cost, nxt;
}edge[maxn];

int tot, pre[maxn], head[maxn], vis[maxn], dis[maxn], S, T;
int n, m, k;
int Want[60][60], Sup[60][60], Cost[60][60][60];

void init() {
    tot = 0;
    memset(head, -1, sizeof(head));
    S = 0; T = n + m + 1 ;
}

void addEdge(int u, int v, int w, int cost) {
    edge[tot].v = v;
    edge[tot].w = w;
    edge[tot].cap = 0;
    edge[tot].cost = cost;
    edge[tot].nxt = head[u];
    head[u] = tot ++;

    edge[tot].v = u;
    edge[tot].w = 0;
    edge[tot].cost = -cost;
    edge[tot].cap = 0;
    edge[tot].nxt = head[v];
    head[v] = tot ++;
}

bool SPFA() {
    memset(dis, INF, sizeof(dis));
    memset(vis, 0, sizeof(vis));
    memset(pre, -1, sizeof(pre));
    queue<int> que;
    que.push(S);
    dis[S] = 0;
    vis[S] = 1;
    pre[S] = -1;
    while(!que.empty()) {
        int u = que.front(); que.pop();
        vis[u] = 0;
        for (int i = head[u]; i + 1; i = edge[i].nxt) {
            if(dis[edge[i].v] > dis[u] + edge[i].cost && edge[i].w > edge[i].cap) {
                dis[edge[i].v] = dis[u] + edge[i].cost;
                pre[edge[i].v] = i;
                if(!vis[edge[i].v]) {
                    vis[edge[i].v] = 1;
                    que.push(edge[i].v);
                }
            }
        }
    }
    if(pre[T] == -1)return 0;
    return 1;
}

int MinCostMaxFlow(int &cost) {
    int Flow = 0, MinCost = INF;
    cost = 0;
    while(SPFA()) {
        for (int i = pre[T]; i + 1; i = pre[edge[i ^ 1].v])
            MinCost = min(MinCost, edge[i].w - edge[i].cap);
        for (int i = pre[T]; i + 1; i = pre[edge[i ^ 1].v]) {
            edge[i].cap += MinCost;
            edge[i ^ 1].cap -= MinCost;
            cost += edge[i].cost * MinCost;
        }
        Flow += MinCost;
    }
    return Flow;
}


int main(int argc, const char * argv[]) {
    while (scanf("%d %d %d", &n, &m, &k) && (n || k || m)) {
        int SumWant[maxn], SumSup[maxn];
        memset(SumSup, 0, sizeof(SumSup));
        memset(SumWant, 0, sizeof(SumWant));
        for (int i = 1; i <= n; i ++)
            for (int j = 1; j <= k; j ++) {
                scanf("%d", &Want[i][j]); //要货
                SumWant[j] += Want[i][j];
            }
        for (int i = 1; i <= m; i ++)
            for (int j = 1; j <= k; j ++) {
                scanf("%d", &Sup[i][j]); //供货
                SumSup[j] += Sup[i][j];
            }
        for (int i = 1; i <= k; i ++)
            for (int j = 1; j <= n; j ++)
                for (int z = 1; z <= m; z ++)
                    scanf("%d", &Cost[z][j][i]);

        bool flag = 0;
        for (int i = 1; i <= k; i ++)
            if(SumSup[i] < SumWant[i]) {
                flag = 1;
                break;
            }
        if(!flag) {
            int MinCost = 0;
            for (int i = 1; i <= k; i ++) {
                init();
                for (int j = 1; j <= m; j ++)
                    addEdge(S, j, Sup[j][i], 0);
                for (int j = 1; j <= n; j ++)
                    addEdge(j + m, T, Want[j][i], 0);
                for (int j = 1; j <= m; j ++)
                    for (int z = 1; z <= n; z ++)
                        addEdge(j, z + m, Want[z][i], Cost[j][z][i]);
                int cost;
                MinCostMaxFlow(cost);
                //printf("%d\n", cost);
                MinCost += cost;
            }
            printf("%d\n", MinCost);
        }else {
            printf("-1\n");
        }

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/henu_jizhideqingwa/article/details/81980985