HDU 1532 Drainage Ditches【HLPP网络流(最高标号预流推进)】

HDU 1532 Drainage Ditches

  • 最大流裸题(同POJ 1273)
  • 代码做了我所能理解的,比较详尽的注释。
    参考教程:最大流算法-最高标号预流推进(HLPP)【PS:这大哥为了缩行,太可怕了QAQ】
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxe = 2e6 + 10;
const int maxn = 1e3 + 10;
const int INF = 0x3f3f3f3f;
struct edge {
	int to, nx, w;
}e[maxe];
int head[maxn];
int sz, n, m;
int prs[maxn], gap[maxn], d[maxn];
//bool able[maxn];
//vector inv[maxn];
void add(int u, int v, int w) {
	e[sz].to = v;//建立正边
	e[sz].w = w;
	e[sz].nx = head[u];
	head[u] = sz++;
	e[sz].to = u;//建立反边
	e[sz].w = 0;
	e[sz].nx = head[v];
	head[v] = sz++;
}
struct cmp {//建立一个,按照h为顺序的大顶堆。
	int x, h;
	cmp(int x = 0, int h = 0) :x(x), h(h) {}
	inline bool operator < (const cmp &a) const { return h < a.h; }//运算符重载
};
priority_queue<cmp> pq;
bool push(int x, int y, int p) {// u, v, id;
	int w = min(prs[x], e[p].w);// 尽可能满流
	e[p].w -= w; e[p ^ 1].w += w; prs[x] -= w; prs[y] += w;
	return w;
}
void Gap(int l, int s, int t) {//如果某点的位置抬高1之后,这个点原来的高度就已经不存在点了
	//那么我们直接把大于这个高度的点全部设置为高度(n+1),让他们直接回流到S
	for (int i = 1; i <= n; i++) {
		if (i != s && i != t && l < d[i] && d[i] <= n) d[i] = n + 1;
	}
}
int maxflow(int s, int t) {
	while (!pq.empty()) pq.pop();
	memset(prs, 0, sizeof prs);
	memset(d, 0, sizeof d);
	memset(gap, 0, sizeof gap);
	d[s] = n; prs[s] = INF; pq.push(cmp(s, d[s]));
	while (!pq.empty()) {
		int x = pq.top().x;
		pq.pop();
		if (!prs[x]) continue;//没有余流
		for (int i = head[x]; i != -1; i = e[i].nx) {
			int v = e[i].to; int w = e[i].w;
			if ((x == s || d[x] == d[v] + 1) && push(x, v, i) && v != t && v != s) {
				pq.push(cmp(v, d[v]));
			}
		}
		if (x != s && x != t && prs[x]) {//有余流,需要抬高一层,如果在s就没必要往上抬了(抬不动了QAQ)
			if (!(--gap[d[x]])) Gap(d[x], s, t);//如果低一层没有元素,发生断档,直接Gap回流给S
			++gap[++d[x]];//抬高一层
			pq.push(cmp(x, d[x]));
		}
	}
	return prs[t];//返回T流量
}
int main() {
	while (~scanf("%d %d", &m, &n)) {
		memset(head, -1, sizeof head); sz = 0;
		for (int i = 1; i <= m; i++) {
			int u, v, w;
			scanf("%d %d %d", &u, &v, &w);
			if (w == 0) continue;//无效边
			add(u, v, w);
		}
		int ans = maxflow(1, n);
		printf("%d\n", ans);
	}
	return 0;
}
//_CRT_SECURE_NO_WARNINGS


你可能感兴趣的:(HLPP,预流推进,网络流,ACM,Algorithm,Template)