费用流爆零 性感多路增广SPFA求调教
查看原帖
费用流爆零 性感多路增广SPFA求调教
1033727
toolazy楼主2024/1/6 20:07

过于玄学了,C++版本不一样,结果居然都不一样?

在本地和你谷IDE上都测过了测试点1(因为只看得到测试点1qwq)。本地能过,你谷IDE只要不吸氧都能过,吸了氧当场爆炸

当前弧优化加了,SPFA是反过来搜的最短路。用的vector邻接表,因为测得比前向星更快(

这是测试点1的数据Input:

10 10 2 5
8 10 862 53
9 4 968 98
4 10 653 79
2 7 237 97
3 9 326 76
1 3 108 8
7 5 994 86
4 9 705 38
1 8 135 18
8 1 252 64

和答案输出:

237 43371

以及性感代码求调(打空格属于是老年人码风力),为了方便各位大大检查,注释附上了:

#include <iostream>
#include <vector>
#include <cstring>
#include <bitset>
#include <queue>
using namespace std;

#define int long long
#define MS 5005

struct MinCostMaxFlow {
	
	// vector存的邻接表,查e的反向边是g[e.to][e.rev]
	struct edge {
		int to, cap, rev, price;
	};
	vector<edge> g[MS];
	int cur[MS], dis[MS];// cur:当前弧优化 dis:spfa最短路
	bitset<MS> vis, inq;// vis:增广时用的标记 inq:spfa用的
	
	void addeDirected(int a, int b, int capacity, int price) {// 加一条有向边
		g[a].push_back({b, capacity, g[b].size(), price});
		g[b].push_back({a, 0, g[a].size() - 1, -price});
	}
	
	bool spfa(int s, int t) {
		memset(cur, 0, sizeof(cur));
		memset(dis, 0x3f, sizeof(dis));
		vis.reset();
		// 上面3条是初始化
		queue<int> q;
		q.push(t);
		inq[t] = true;
		dis[t] = 0;
		while (!q.empty()) {
			int u = q.front();
			q.pop();
			inq[u] = false;
			for (edge re : g[u]) {// 查的是反向边,因为是反过来的最短路
				int v = re.to, w = -re.price;
				if (g[v][re.rev].cap && dis[u] + w < dis[v]) {
					dis[v] = dis[u] + w;
					if (!inq[v]) {
						inq[v] = true;
						q.push(v);
					}
				}
			}
		}
		return dis[s] != dis[0];// dis[0]用不上,就是inf嘛
	}
	
	int augment(int u, int t, int neck, int & cost) {// neck就是瓶颈,cost就是花费,返回流量
		if (u == t)
			return neck;
		int flow = 0;
		vis[u] = true;// 打上标记
		for (int & idx = cur[u]; idx < g[u].size(); idx ++) {
			edge & e = g[u][idx];
			int v = e.to, w = e.price;
			if (e.cap && !vis[v] && dis[u] == dis[v] + w) {
				int add = augment(v, t, min(e.cap, neck), cost);
				if (!add) {// 剪枝,但是好像没用,因为已经有vis的存在了
					dis[v] = 0;
					continue;
				}
				neck -= add;
				e.cap -= add;
				g[v][e.rev].cap += add;
				flow += add;
				cost += add * w;
			}
			if (neck == 0)
				return flow;
		}
		return flow;
	}
	
	int spfaMCMF(int s, int t, int & cost) {
		int flow = 0;
		while (spfa(s, t))
			while (int add = augment(s, t, dis[0], cost))
				flow += add;
		return flow;
	}
	
} g;

// 主函数没啥好看的
main() {
	ios :: sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int n, m, s, t, flow, cost;
	cin >> n >> m >> s >> t;
	while (m --) {
		int a, b, capacity, price;
		cin >> a >> b >> capacity >> price;
		g.addeDirected(a, b, capacity, price);
	}
	flow = g.spfaMCMF(s, t, cost);
	cout << flow << ' ' << cost;
	return 0;
}
2024/1/6 20:07
加载中...