POJ 2516 Minimum Cost

最小费.

主要是这题有K种货物搞得关系很复杂, 开始建图卡住, 其实把k种货物分开来建k次图跑k次就好了.

然后判断最大流和是否满足需求, 若满足则输出最小费和, 若不满足, 则输出-1.

貌似还可以用KM


代码:

//最小费用流
//	建k次图... 最小费

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN = 200;
const int MAXM = 40005;
const int INF = 1<<30;
int mincost,maxflow;
int n,m;
int U[MAXM],V[MAXM],cap[MAXM],flow[MAXM],cost[MAXM],next[MAXM];
int head[MAXN],pre[MAXN],Edge[MAXN],dis[MAXN];
int num;
void addEdge(int u,int v,int Cap,int Cost)
{
	flow[num] = flow[num+1] = 0;
	V[num] = v;
	U[num] = u;
	cap[num] = Cap;
	cost[num] = Cost;
	next[num] = head[u];
	head[u] = num++;
	
	V[num] = u;
	U[num] = v;
	cap[num] = 0;
	cost[num] = -Cost;
	next[num] = head[v];
	head[v] = num++;
}

void MCMF(int st,int ed)
{
	queue<int> q;
	memset(flow,0,sizeof(flow));
	mincost = maxflow = 0;
	for(;;)
	{
		bool inq[MAXN];
		for(int i = st;i <= ed;++i)		dis[i] = (i == st ? 0 : INF);
		memset(inq,0,sizeof(inq));
		q.push(st);
		while(!q.empty())
		{
			int u = q.front();	q.pop();
			inq[u] = 0;
			for(int e = head[u];e != -1;e = next[e])
			{
				if(cap[e] > flow[e] && dis[u] + cost[e] < dis[V[e]])
				{
					dis[V[e]] = dis[u] + cost[e];
					pre[V[e]] = U[e]; 
					Edge[V[e]] = e;
					if(!inq[V[e]])
					{
						q.push(V[e]);
						inq[V[e]] = 1;
					}
				}
			}
		}//SPFA增广
		if(dis[ed] == INF)	break;
		int delta = INF;//delta为可改进量
		for(int u = ed;u != st;u = pre[u])
			delta = min(delta,cap[Edge[u]] - flow[Edge[u]]);//遍历最短路径的边,并修改可改进量
		for(int u = ed;u != st;u = pre[u])
		{
			flow[Edge[u]] += delta;//更新正向流量
			flow[Edge[u] ^ 1] -= delta;//通过异或1取得反向边的序号,并更新反向流量
		}
		mincost += dis[ed] * delta;
		maxflow += delta;
	}
}

int sell[52][52];
int buy[52][52];
int value[52][52][52];
int main()
{
	//	buildGraphs
	int K;
	while(scanf("%d%d%d", &n, &m, &K) == 3)
	{
		if(!n && !m && !K) break;
		int need = 0;
		int totflow = 0;
		int totcost = 0;
		for(int i=0; i<n; i++)
			for(int k=0; k<K; k++)
			{
				scanf("%d", &buy[k][i]);	//n个买家
				need+=buy[k][i];
			}
		for(int i=0; i<m; i++)
			for(int k=0; k<K; k++)
			{
				scanf("%d", &sell[k][i]);	//m个仓库
			}
		for(int k=0; k<K; k++)
			for(int i=0; i<n; i++)
				for(int j=0; j<m; j++)
				{
					scanf("%d", &value[k][i][j]);		//j->i
				}
		for(int k=0; k<K; k++)
		{
			num = 0;
			memset(head,-1,sizeof(head));				// 0 卖 1~m 买 m+1~m+n 汇 m+n+1
			for(int i=0; i<m; i++)
			{
				addEdge(0,i+1,sell[k][i],0);
			}
			for(int i=0; i<n; i++)
			{
				addEdge(i+1+m, m+n+1, buy[k][i], 0);
			}
			for(int i=0; i<n; i++)
				for(int j=0; j<m; j++)	//卖
				{
					addEdge(j+1, i+1+m, INF, value[k][i][j]);
				}
			//MCMF
			MCMF(0,n+m+1);
			totcost += mincost;
			totflow += maxflow;
			//printf("%d\n",mincost);
		}
		if(totflow!=need) totcost = -1;
		printf("%d\n", totcost);
	}

}


发布了179 篇原创文章 · 获赞 5 · 访问量 20万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览