最小费用最大流SPFA模板

P3381 【模板】最小费用最大流

最小费用最大流SPFA模板_第1张图片

模板代码:

/*---------------------------------
 *File name: 最小费用最大流.cpp
 *Creation date: 2020-05-20 11:56
 *-------------------------------*/
#include
#include
#include
#include
using namespace std;
const int maxn = 5e3 + 5;
const int maxm = 5e4 + 5;
const int inf = 0x3f3f3f3f;

struct Edge{
	int to, cost, flow, next;
}edge[maxm << 1];
int head[maxn], cnt = 0;

bool vis[maxn];

int n, m, s, t;

int flow[maxn], cost[maxn];//flow[i]:从源点到i的流量,cost[i]:从源点到i的总花费
int pre[maxn], from[maxn];//pre[i]:值为点,代表i点的前驱点。from[i]:值为边号,连接pre[i]和i的边的序号

inline void Add_Edge(int u, int v, int w, int c){
	edge[cnt].next = head[u];
	edge[cnt].to = v;
	edge[cnt].flow = w;
	edge[cnt].cost = c;
	head[u] = cnt++;
}

inline bool SPFA(){
	for(int i = 0; i < maxn; ++i) vis[i] = 0, flow[i] = cost[i] = inf;//初始化数组
	queue q;
	q.push(s);
	vis[s] = 1, cost[s] = 0, pre[t] = -1;//标记s入队
	while(!q.empty()){
		int cur = q.front(); q.pop();
		vis[cur] = 0;//标记cur出队
		for(int i = head[cur]; i != -1; i = edge[i].next){
			int to = edge[i].to;
			if(edge[i].flow > 0 && cost[to] > cost[cur] + edge[i].cost){//残量大于0且满足松弛条件
				cost[to] = cost[cur] + edge[i].cost;//更新
				pre[to] = cur;//to的前驱结点更新为cur
				from[to] = i;//连接cur与to的边的序号为i
				flow[to] = min(flow[cur], edge[i].flow);//更新流量
				if(!vis[to]){
					vis[to] = 1;
					q.push(to);
				}
			}
		}
	}
	return pre[t] != -1;
}

inline void MCMF(){
	int MaxFlow, MinCost;
	MaxFlow = MinCost = 0;
	while(SPFA()){
		int cur = t;
		MaxFlow += flow[t];
		MinCost += flow[t] * cost[t];
		while(cur != s){//从t点回溯更新残量
			edge[from[cur]].flow -= flow[t];
			edge[from[cur] ^ 1].flow += flow[t];
			cur = pre[cur];
		}
	}
	printf("%d %d\n", MaxFlow, MinCost);
}

int main(){
	memset(head, -1, sizeof(head));
	scanf("%d %d %d %d", &n, &m, &s, &t);
	for(int i = 1; i <= m; ++i){
		int u, v, w, c;
		scanf("%d %d %d %d", &u, &v, &w, &c);
		Add_Edge(u, v, w, c);
		Add_Edge(v, u, 0, -c);
	}
	MCMF();
	return 0;
}

 

你可能感兴趣的:(算法学习,题解,模板)