#网络流,费用流#洛谷 3381 【模板】最小费用最大流

题目

给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。


分析

这里写图片描述
spfa然后修改每次的流量。


代码

#include <cstdio>
#include <queue>
using namespace std;
struct node{int y,next,w,c;}e[100005]; bool v[5001];
int dis[5001],answer,ans,x,y,w,c,n,m,s,t,k=1,ls[5001],pre[5001];
void add(int x,int y,int w,int c){
	e[++k].y=y; e[k].w=w; e[k].c=c; e[k].next=ls[x]; ls[x]=k;
	e[++k].y=x; e[k].w=0; e[k].c=-c;e[k].next=ls[y]; ls[y]=k;
}
bool spfa(){//spfa
	queue<int>q; 
	for (int i=1;i<=n;i++) v[i]=0;
	for (int i=1;i<=n;i++) dis[i]=707406378;
	dis[s]=0; v[s]=1; q.push(s);
	while (q.size()){
		int u=q.front(); q.pop();
		for (int i=ls[u];i;i=e[i].next)
		if (e[i].w>0&&dis[u]+e[i].c<dis[e[i].y]){//有容量且费用更少吗
			dis[e[i].y]=dis[u]+e[i].c; pre[e[i].y]=i;//记录前驱
			if (!v[e[i].y]) v[e[i].y]=1,q.push(e[i].y);
		}
		v[u]=0;
	}
	if (dis[t]<707406378) return 1; else return 0;
}
void update(){
	m=2147483647; int x=t;
	while (x!=s) m=min(m,e[pre[x]].w),x=e[pre[x]^1].y;//统计
	ans+=dis[t]*m; answer+=m; x=t; 
	while (x!=s) e[pre[x]].w-=m,e[pre[x]^1].w+=m,x=e[pre[x]^1].y;//回去修改
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i=1;i<=m;i++) scanf("%d%d%d%d",&x,&y,&w,&c),add(x,y,w,c);
	while (spfa()) update();
	return !printf("%d %d",answer,ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值