Incorrect Flow,CF708D,最小费用最大流

本文介绍了一种解决网络流中最小费用最大流问题的方法。通过构造特定的网络图,并运用SPFA算法寻找增广路径,实现从源点到汇点的最小费用流。文章详细解释了如何处理流量不平衡的情况,确保所有节点满足流量守恒原则。
部署运行你感兴趣的模型镜像

正题

      显然一条边要么增加流量,要么减少流量,增加流量相当于正着流,减少流量相当于反着流,根据c与f的关系来分段计费,对于那些原来不满足流量平衡的点,如果入度过多,那么就从S向其连容量为入度-出度的边,表示从这个点要找那么多的容量流出去,出度过多同理.

      然后跑最小费用最大流即可,由于上限其实是可以到正无穷的,所以必然有解.

#include<bits/stdc++.h>
using namespace std;

const int N=110,M=1010;
struct edge{
	int y,nex,f,c;
}s[M<<1];
int first[N],len=1;
int op[N],d[N],pre[N],mmin[N];
bool tf[N];
int n,m,s1,t1;
queue<int> f;

void ins(int x,int y,int f,int c){
	s[++len]=(edge){y,first[x],f,c};first[x]=len;
	s[++len]=(edge){x,first[y],0,-c};first[y]=len;
}

int SPFA(){
	for(int i=1;i<=t1;i++) d[i]=1e9;
	d[s1]=0;tf[s1]=true;mmin[s1]=1e9;
	f.push(s1);
	while(!f.empty()){
		int x=f.front();f.pop();tf[x]=false;
		for(int i=first[x];i!=0;i=s[i].nex) if(s[i].f && d[s[i].y]>d[x]+s[i].c){
			d[s[i].y]=d[x]+s[i].c;
			pre[s[i].y]=i;
			mmin[s[i].y]=min(mmin[x],s[i].f);
			if(!tf[s[i].y]) f.push(s[i].y),tf[s[i].y]=true;
		}
	}
	if(d[t1]==1e9) return 1e9;
	int now=t1;
	while(now!=s1){
		s[pre[now]].f-=mmin[t1];
		s[pre[now]^1].f+=mmin[t1];
		now=s[pre[now]^1].y;
	}
	return mmin[t1]*d[t1];
}

int MCMF(){
	int tot=0;
	while(1){
		int dx=SPFA();
		if(dx==1e9) break;
		tot+=dx;
	}
	return tot;
}

int main(){
	scanf("%d %d",&n,&m);s1=n+1;t1=s1+1;
	int x,y,f,c;
	int ans=0;
	for(int i=1;i<=m;i++){
		scanf("%d %d %d %d",&x,&y,&c,&f);
		op[x]-=f;op[y]+=f;
		if(f<=c){
			if(f<c) ins(x,y,c-f,1);
			ins(x,y,1e9,2);
			ins(y,x,f,1);
		}
		else{
			ans+=f-c;
			ins(x,y,1e9,2);
			ins(y,x,f-c,0);
			ins(y,x,c,1);
		}
	}
	for(int i=1;i<=n;i++) 
		if(op[i]>0) ins(s1,i,op[i],0);
		else if(op[i]<0) ins(i,t1,-op[i],0);
	ins(n,1,1e9,0);
	printf("%d\n",ans+MCMF());
}

 

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值