最小费用最大流

有了上一篇文章最大流的基础,理解最小费用最大流就很容易了,但是我还是想了挺久的。当我看到最小费用最大流问题这篇文章,才开始觉悟。于是做了如下实现。

/*
	每次找出最短路径(该路径的单位费用和最小)记录该路径(next数组)
	直到找不出这样一条路径(实际上是没有到达终点的路,因为图中的路是会不停的变动)。我们这里的是Distance[0]>=MAX

*/

#include<iostream>
using namespace std;
#define MAX 1024

int nodes,edges;//节点数和边数
int capacity[MAX][MAX];//节点之间的流量
int cost[MAX][MAX];//节点之间的单位费用

int minCost=0;//统计最小费用
int next[MAX];//为了记录最短路径

int Distance[MAX];//表示每个节点到终点的费用
inline int min(int a,int b)
{
	return a<b?a:b;
}
void resetThePath()//找出最短路径,这里还需优化。
{
	int i,j;
	for(i=0;i<nodes-1;i++)
		Distance[i]=MAX;
	Distance[nodes-1]=0;
	next[nodes-1]=-1;
	
	for(i=nodes-1;i>=0;i--)
	{
		for(j=0;j<nodes;j++)
		{
			if(cost[j][i]!=MAX)
			{
				if(Distance[j]>(Distance[i]+cost[j][i]))
				{
					Distance[j]=Distance[i]+cost[j][i];
					next[j]=i;
				}
			}
		}	
	}

	for(i=nodes-1;i>=0;i--)
	{
		for(j=0;j<nodes;j++)
		{
			if(cost[j][i]!=MAX)
			{
				if(Distance[j]>(Distance[i]+cost[j][i]))
				{
					Distance[j]=Distance[i]+cost[j][i];
					next[j]=i;
				}
		}	
	}	
}

void minCostMaxFlow()
{
	while(1)
	{
		int i;
		resetThePath();
		if(Distance[0]>=MAX)//没有最短路径
			break;
		int increase=MAX;//本次最短路径中的流量
		for(i=0;next[i]!=-1;i=next[i])
		{
			increase=min(increase,capacity[i][next[i]]);
		}
		for(i=0;next[i]!=-1;i=next[i])//改变图的路径信息
		{
			capacity[i][next[i]]-=increase;
			capacity[next[i]][i]+=increase;
			if(cost[next[i]][i]==MAX)
				cost[next[i]][i]=cost[i][next[i]]*(-1);
			if(!capacity[i][next[i]])
				cost[i][next[i]]=MAX;
		}
		minCost+=Distance[0]*increase;
	}		
}

void main()
{
	while(1)
	{
		cin>>nodes>>edges;
		int i,j;
		for(i=0;i<nodes;i++)
		{
			for(j=0;j<nodes;j++)
				capacity[i][j]=0;
			for(j=0;j<nodes;j++)
				cost[i][j]=MAX;
		}
		int firstnode,secondnode,capa,cos;
		for(i=0;i<edges;i++)
		{
			cin>>firstnode>>secondnode>>capa>>cos;
			capacity[firstnode][secondnode]=capa;
			cost[firstnode][secondnode]=cos;
		}
		minCostMaxFlow();
		cout<<minCost<<endl;
	}
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值