您的位置:首页 > 其它

POJ 2516 Minimum Cost 最小费用最大流

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

题解:因为 K 种产品互相不干扰,所以关键是把 K 种产品分开求解。
#include <queue>
#include <iostream>
using namespace std;

#define N 155
#define INF 999999

int need

, store

, cost

;
int cap

, flow

, fee

;
int pre
, dis
, vis
;
int n, m, kind, s, t;

void spfa()
{
queue<int> que;
memset(vis,0,sizeof(vis));
memset(pre,-1,sizeof(pre));

for ( int i = 0; i <= t; i++ )
dis[i] = INF;
dis[s] = 0;
vis[s] = 1;
que.push(s);

while ( ! que.empty() )
{
int u = que.front();
que.pop();
vis[u] = 0;
for ( int v = 0; v <= t; v++ )
{
if ( cap[u][v] > flow[u][v] && dis[v] > dis[u] + fee[u][v] )
{
dis[v] = dis[u] + fee[u][v];
pre[v] = u;
if ( ! vis[v] )
{
que.push(v);
vis[v] = 1;
}
}
}
}
}

void mcmf ()
{
while ( 1 )
{
spfa();
if ( pre[t] == -1 )
return;

int tt = t;
int minflow = INF;

while ( pre[tt] != -1 )
{
if ( minflow > cap[pre[tt]][tt] - flow[pre[tt]][tt] )
minflow = cap[pre[tt]][tt] - flow[pre[tt]][tt];
tt = pre[tt];
}

tt = t;
while ( pre[tt] != -1 )
{
flow[pre[tt]][tt] += minflow;
flow[tt][pre[tt]] -= minflow;
tt = pre[tt];
}
}
}

void solve()
{
int i, j, k, res = 0;
for ( k = 1; k <= kind; k++ )
{
memset(cap,0,sizeof(cap));
memset(fee,0,sizeof(fee));
memset(flow,0,sizeof(flow));

for ( i = 1; i <= m; i++ )
cap[s][i] = store[i][k];

for ( i = 1; i <= m; i++ )
for ( j = 1; j <= n; j++ )
cap[i][j+m] = store[i][k];

for ( i = 1; i <= n; i++ )
cap[i+m][t] = need[i][k];

for ( i = 1; i <= m; i++ )
for ( j = 1; j <= n; j++ )
{
fee[i][j+m] = cost[k][j][i]; // 注意是cost[k][j][i]。这地方调了一个多小时!!!
fee[j+m][i] = -fee[i][j+m];
}

mcmf();

for ( i = 1; i <= m; i++ )
for ( j = 1; j <= n; j++ )
res += flow[i][j+m] * fee[i][j+m];
}
printf("%d\n",res);
}

int main()
{
while ( scanf("%d%d%d",&n,&m,&kind) )
{
s = 0;
t = m + n + 1;

if ( !n && !m && !kind ) break;

int i, j, k;
for ( i = 1; i <= n; i++ )
for ( j = 1; j <= kind; j++ )
scanf("%d",&need[i][j]);

for ( i = 1; i <= m; i++ )
for ( j = 1; j <= kind; j++ )
scanf("%d",&store[i][j]);

for ( k = 1; k <= kind; k++ )
for ( i = 1; i <= n; i++ )
for ( j = 1; j <= m; j++ )
scanf("%d",&cost[k][i][j]);

for ( k = 1; k <= kind; k++ )
{
int totalNeed = 0;
int totalStore = 0;

for ( i = 1; i <= n; i++ )
totalNeed += need[i][k];

for ( i = 1; i <= m; i++ )
totalStore += store[i][k];

if ( totalStore < totalNeed )
{
printf("-1\n");
goto next;
}
}

solve();
next:;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  产品 存储