现在的位置: 首页 > 综合 > 正文

POJ 2516 Minimum Cost 最小费用最大流

2013年08月30日 ⁄ 综合 ⁄ 共 1924字 ⁄ 字号 评论关闭

题意:有N个客户,M个仓库,和K种货物。已知每个客户需要每种货物的数量,每个仓库存储每种货物的数量,每个仓库运输各种货物去各个客户的单位费用。判断所有的仓库能否满足所有客户的需求,如果可以,求出最少的运输总费用。
题解:因为 K 种产品互相不干扰,所以关键是把 K 种产品分开求解。

#include <queue>
#include <iostream>
using namespace std;

#define N 155
#define INF 999999

int need[N][N], store[N][N], cost[N][N][N];
int cap[N][N], flow[N][N], fee[N][N];
int pre[N], dis[N], vis[N];
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;
}

抱歉!评论已关闭.