[洛谷P3381]【模板】最小费用最大流

题目大意:最小费用最大流

题解:最小费用最大流

卡点:1.太久不打MCMF,反向弧费用未取相反数

C++ Code:

#include <cstdio>
#include <cstring>
#define maxn 5010
#define maxm 50100
using namespace std;
const int inf = 0x3f3f3f3f;
int n, m, S, T, MF;
int q[maxm], h, t;
int d[maxn], pre[maxn];
bool vis[maxn];
int head[maxn], cnt = 2;
struct Edge {
	int to, nxt, w, cost;
} e[maxm << 1];
void add(int a, int b, int c, int d) {
	e[cnt] = (Edge) {b, head[a], c, d}; head[a] = cnt;
	e[cnt ^ 1] = (Edge) {a, head[b], 0, -d}; head[b] = cnt ^ 1;
	cnt += 2;
}
inline int min(int a, int b) {return a < b ? a : b;}
bool spfa() {
	memset(d, 0x3f, sizeof d);
	d[q[h = t = 0] = S] = 0;
	while (h <= t) {
		int u = q[h++];
		vis[u] = false;
		for (int i = head[u]; i; i = e[i].nxt) {
			int v = e[i].to;
			if (e[i].w && d[v] > d[u] + e[i].cost) {
				d[v] = d[u] + e[i].cost;
				pre[v] = i;
				if (!vis[v]) {
					q[++t] = v;
					vis[v] = true;
				}
			}
		}
	}
	return d[T] != inf;
}
int update() {
	int ans, mf = inf;
	for (int i = pre[T]; i; i = pre[e[i ^ 1].to]) mf = min(mf, e[i].w);
	ans = mf * d[T];
	MF += mf;
	for (int i = pre[T]; i; i = pre[e[i ^ 1].to]) e[i].w -= mf, e[i ^ 1].w += mf;
	return ans;
}
void MCMF() {
	int ans = 0;
	while (spfa()) ans += update();
	printf("%d %d
", MF, ans);
}
int main() {
	scanf("%d%d%d%d", &n, &m, &S, &T);
	for (int i = 0; i < m; i++) {
		int a, b, c, d;
		scanf("%d%d%d%d", &a, &b, &c, &d);
		add(a, b, c, d);
	}
	MCMF();
	return 0;
}

  

原文地址:https://www.cnblogs.com/Memory-of-winter/p/9371954.html