最大流,费用流模板

本文详细介绍了两种网络流算法:Dinic算法实现的最大流模板和结合bfs与sfpa算法的最小费用最大流模板。前者适用于寻找图中源点到汇点的最大流值,后者则在最大流的基础上加入费用考量,寻求最小总费用的最大流解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最大流模板(Dinic)

#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<stdio.h>
#include<cstring>
typedef long long int ll;
const ll inf = 2005020600;
using namespace std;

int n,m,s,t;
const int maxn = 520010;  
struct edge{
    int v,next;
    ll f;
}e[maxn];
int head[maxn],tot = 1;
void add(int u,int v,ll f){
    e[++tot].v = v;
    e[tot].f = f;
    e[tot].next = head[u];
    head[u] = tot;
}
ll dep[maxn];
int now[maxn];
inline bool bfs(){
    for(int i = 1; i <= n; i++)dep[i] = -1;
    queue<int>st;
    st.push(s);
    dep[s] = 0;
    now[s] = head[s];//当前弧优化
    while(!st.empty()){
        int u = st.front();st.pop();
        for(int i = head[u]; i ; i = e[i].next){
            int v = e[i].v;
            if(dep[v] == -1 && e[i].f > 0){
                dep[v] = dep[u] + 1;
                st.push(v);
                now[v] = head[v];//当前弧优化
                if(v == t)return 1;
            }
        }
    }
    return 0;
}
inline ll dfs(int u,ll flow){
    if(u == t)return flow;
    ll rest = 0;
    for(int i = now[u]; i && flow > 0; i = e[i].next){//当前弧优化
        now[u] = i;//当前弧优化
        int v = e[i].v;
        if((dep[v] == dep[u] + 1) && e[i].f > 0){
            ll temp = dfs(v,min(flow,e[i].f));
            if(temp == 0)dep[v] = -1;//炸点优化
            rest += temp;//通过这个点流出去的流量
            flow -= temp;//这个点剩余流流
            e[i].f -= temp;
            e[i ^ 1].f += temp;
        }
    }
    return rest;//返回一共流出去的流量
}
void maxflow(){
    ll ans = 0;
    while(bfs()){
        ans += dfs(s,(ll)inf);
    }
    printf("%lld\n",ans);
}
int main(){
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i = 1; i <= m; i++){
        ll w;
        int u,v;scanf("%d%d%lld",&u,&v,&w);
        add(u,v,w);add(v,u,0);
    }
    maxflow();
    return 0;
}

最小费用最大流模板(bfs+sfpa)

#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstring>
#include<stdio.h>
using namespace std;

const int maxn = 2e5 + 10;
struct edge{
	int v,w,f,next;
}e[maxn];
int head[maxn],tot = 1;
void add(int u,int v,int w,int f){
	e[++tot].v = v;
	e[tot].f = f;
	e[tot].w = w;
	e[tot].next = head[u];
	head[u] = tot;
}
int n,m,s,t;
int pre[maxn],dis[maxn];
bool vis[maxn];
int flow[maxn];
int spfa(){
	memset(flow,0,sizeof(flow));
	memset(vis,0,sizeof(vis));
	memset(dis,0x3f,sizeof(dis));
	queue<int>st;
	st.push(s);
	dis[s] = 0,vis[s] = 1,flow[s] = 1 << 30;
	while(!st.empty()){
		int u = st.front();st.pop();
		vis[u] = 0;
		for(int i = head[u]; i ;i = e[i].next){
			if(e[i].f <= 0)continue;
			if(dis[e[i].v] > e[i].w + dis[u]){
				dis[e[i].v] = e[i].w + dis[u];
				pre[e[i].v] = i;
				flow[e[i].v] = min(flow[u],e[i].f);
				if(!vis[e[i].v]){
					vis[e[i].v] = 1;
					st.push(e[i].v);
				}
			}
		}
	}
	return dis[t] != 1061109567;
}
void mcmf(){
	int maxflow = 0,mincost = 0;
	while(spfa()){
		maxflow += flow[t];
		mincost += flow[t] * dis[t];
		int p = t;
		while(p != s){
			e[pre[p]].f -= flow[t];
			e[pre[p] ^ 1].f += flow[t];
			p = e[pre[p] ^ 1].v;
		}
	}
	cout<<maxflow<<" "<<mincost<<endl;
}
int main(){
	scanf("%d%d%d%d",&n,&m,&s,&t);
	for(int i = 1; i <= m; i++){
		int u,v,w,f;scanf("%d%d%d%d",&u,&v,&f,&w);
		add(u,v,w,f);
		add(v,u,-w,0);//反边负权
	}
	mcmf();
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值