poj 2516 Minimum Cost 最小费用最大流

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

分析:首先判断每个仓库的库存是否满足N个客户的需要,在这个条件下,因为有K种货物,而K种货物又是从不同的仓库发出的,所以对于每一种货物,我们可以设想起其为一种费用,对每种货物进行一次 最小费用最大流即可。

View Code
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
#define re(i,n) for(int i=0;i<n;i++)
#define re1(i,n) for(int i=1;i<=n;i++)
#define inf (1<<29)
const int maxn = 110;
int n , m , k;
int cap[maxn][maxn];
int cost[maxn][maxn];
int p[maxn];
bool inq[maxn];
int dist[maxn];
queue<int> Q;
int ans;

bool spfa(int s , int t) {
    int u , v;
    memset(inq,false,sizeof(inq));
    for(int i=s;i<=t;i++) dist[i] = inf;
    dist[s] = 0;
    Q.push(s);
    inq[s] = true;
    while(!Q.empty()) {
        u = Q.front();  Q.pop();
        inq[u] = false;
        for(v=s;v<=t;v++) {
            if(cap[u][v] > 0 && dist[u]+cost[u][v] < dist[v]) {
                dist[v] = dist[u] + cost[u][v];
                p[v] = u;
                if(!inq[v]) { inq[v] = true; Q.push(v); }
            }
        }
    }
    return dist[t] != inf;
}

void edmonds_karp(int s , int t) {
    int u , a = inf;
    for(u=t;u!=s;u=p[u])
        if(a > cap[p[u]][u]) a = cap[p[u]][u];
    for(u=t;u!=s;u=p[u]) {
        cap[p[u]][u] -= a;
        cap[u][p[u]] += a;
        ans += cost[p[u]][u] * a;
    }
}

int main() {
    int need[maxn][maxn] , needTotal[maxn];
    int have[maxn][maxn] , haveTotal[maxn];
    while(~scanf("%d%d%d",&n,&m,&k) && n) {
        memset(needTotal,0,sizeof(needTotal));
        memset(haveTotal,0,sizeof(haveTotal));
        re1(i,n) re1(j,k) {
            scanf("%d",&need[i][j]);
            needTotal[j] += need[i][j];
        }
        re1(i,m) re1(j,k) {
            scanf("%d",&have[i][j]);
            haveTotal[j] += have[i][j];
        }
        bool flag = true;
        re1(i,k) {
            if(needTotal[i] > haveTotal[i]) {
                flag = false;
                break;
            }
        }
        ans = 0;
        re1(i,k) {
            memset(cap,0,sizeof(cap));
            re1(j,n) re1(t,m) {
                scanf("%d",&cost[t][j+m]);
                cost[j+m][t] = -cost[t][j+m];
                cap[t][j+m] = inf;
            }
            if(!flag) continue;
            re1(j,m) {
                cap[0][j] = have[j][i];
                cost[0][j] = cost[j][0] = 0;
            }
            re1(j,n) {
                cap[j+m][n+m+1] = need[j][i];
                cost[j+m][n+m+1] = cost[n+m+1][j+m] = 0;
            }
            while(spfa(0,n+m+1)) edmonds_karp(0,n+m+1);
        }
        if(!flag) ans = -1;
        printf("%d\n",ans);
    }
    return 0;
}
posted @ 2012-07-04 18:33  lenohoo  阅读(138)  评论(0)    收藏  举报