图论(十)——网络流的最大最小费用最大流问题

费用流

在求网络的最大流的同时加上一个条件:每条边的流过流的单位费用,由此得出费用流的问题
【其实费用流就可以算是最大流和最短路最长路的综合】
费用流问题分为两类:
最小费用最大流(最大流+最短路)
最大费用最大流(最大流+最长路)

最小费用最大流

为什么说最小费用最大流就是最大流+最短路呢,
可以这样想:
有一条流量为f的增广路,对于其中的每一条边都有一个单位费用cost[i],每条边的流量都是f,求出这一条增广路上所有边的单位费用之和Cost,那么这一条增广路的花费就是Cost*f


操作方法:

  1. 先用最短路算法寻找出一条单位费用之和最小的路
  2. 记录这条路上的最小容量,更新这条路上的所有边
  3. 重复上述操作,知道没有增广路

代码实现:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int len_edge
const int len_node

struct Edge{
	int to,weight,cost
}edge[len_edge];
int head[len_node],nxt[len_edge],cnt;
int num_node,num_edge,s,t;

struct Dis{
	int id,dis;
	Dis(int order,int d){
		id=order;
		dis=d;
	}
	
	bool operator < (const Dis &a) const {
		return dis>a.dis;
	}
};

void init(){
	memset(head,-1,sizeof(head));
	memset(nxt,-1,sizeof(nxt));
	cnt=-1;
	
	
}

void addEdge(int u,int v,int w,int c){
	edge[++cnt].to=v;
	edge[cnt].weight=w;
	edge[cnt].cost=c;
	nxt[cnt]=head[u];
	head[u]=cnt;
	
	edge[++cnt].to=u;
	edge[cnt].weight=0;
	edge[cnt].cost=-c;
	nxt[cnt]=head[v];
	head[v]=cnt;
}

int dis[len_node],inq[len_node],x,y;
int prePoint[len_node],preEdge[len_node];
Dis point;
bool SPFA(){   //因为有负权边(-c)  所以不能使用dijkstra算法 
	memset(dis,inf,sizeof(dis));
	memset(inq,0,sizeof(inq));
	memset(prePoint,-1,sizeof(prePoint));
	
	priority_queue<Dis>node;
	node.push( Dis(s,0) );
	dis[s]=0;
	inq[s]=1;
	
	while(!node.empty()){
		point=node.front();
		node.pop();
		x=point.id;
		inq[x]=0;
		
		for(int i=head[x];i!=-1;i=nxt[i]){
			y=edge[i].to;
			if(edge[i].weight){
				if(dis[y]>dis[x]+edge[i].cost){
					dis[y]=dis[x]+edge[i].cost;
					prePoint[y]=x;
					preEdge[y]=i;
					if(!inq[y]){
						node.push( Dis(y,dis[y]) );
						inq[y]=1;
					}
				}
			}
		}
	}
	
	return dis[t]!=inf;
}

int mincost(){
	int id,flow,cost=0,maxflow=0;
	while(SPFA()){
		x=t;
		flow=inf;
		while(prePoint[x]!=-1){   //求这一条增广路的流 
			id=preEdge[x];
			flow=min(flow,edge[id].weight);
			x=prePoint[x];
		}
		
		x=t;
		while(prePoint[x]!=-1){   //更新增广路上的容量 
			id=preEdge[x];
			
			edge[id].weight-=flow;
			edge[id^1].weight+=flow;
		}
		
		cost+=flow*dis[t];
		//maxflow+=flow;   如果需要求出最大流的话 
	}
	
	return cost;
}

int main(){
	//按照题目的逻辑写就可以了 
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值