网络流(HLPP--预流推进)模板

题目连接

学习路径: 预流推进 O(N^{2}* \sqrt[]{M}

https://www.luogu.org/blog/ONE-PIECE/jiu-ji-di-zui-tai-liu-suan-fa-isap-yu-hlpp

https://www.luogu.org/problemnew/solution/P4722

AC:朴素版本预流推进(刚刚好卡过)

#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
const int maxn = 1e4 + 5, maxm = 2e6 + 5, inf = 0x3f3f3f3f;
int n, m, s, t;
int cnt = 0;
int head[maxn], gap[maxn], h[maxn], e[maxn];
bool inq[maxn];
struct cmp {
	inline bool operator () (int a, int b) const {
		return h[a] < h[b];
	}
};
priority_queue<int,vector<int>,cmp> pq;

struct Node {
	int v, flow, next;
}edge[maxm];
//建边 
inline void addedge(int u, int v, int flow) {
	edge[cnt] = {v, flow, head[u]};
	head[u] = cnt++;
	edge[cnt] = {u, 0, head[v]};
	head[v] = cnt++;
}
// 反向分层 
inline bool Bfs() {
	memset(h, inf, sizeof(h));
	queue<int> q;
	q.push(t), h[t] = 0;
	while(!q.empty()) {
		int u = q.front();
		q.pop();
		for(int i = head[u]; i; i = edge[i].next){
			int v = edge[i].v;
			if (edge[i ^ 1].flow && h[v] > h[u] + 1) {
				h[v] = h[u] + 1;
				q.push(v);
			}
		}
	}
	return h[s] != inf;
}
//u点推流 
inline void push_(int u) {
	register int i;
	for(i = head[u]; i != -1; i = edge[i].next){
		int v = edge[i].v;
		int flow = edge[i].flow;
		if (flow && (h[v]+1 == h[u])){
            int mi = min(e[u], flow);
            edge[i].flow -= mi;
            edge[i^1].flow += mi;
            e[u] -= mi;
            e[v] += mi;
			if (v != s && v != t && !inq[v]) {
				pq.push(v);
				inq[v] = 1;
			}
			if ( e[u] == 0 ) break;
		}
	}
}
//更改 点的高度 
inline void relabel(int u) {
	register int i;
	h[u] = inf;
	for (i = head[u]; i != -1; i = edge[i].next) {
		int v = edge[i].v;
		int flow = edge[i].flow;
		if (flow && (h[v] + 1 < h[u])) {
			h[u] = h[v] + 1;
		}
	}
}

// HLPP开始预流推进
inline int Hlpp(){
	register int i;
	if ( !Bfs() ) return 0;
	h[s] = n;
	memset(gap, 0, sizeof(gap));
	for(i = 1; i <= n; ++i) if(h[i] != inf) gap[h[i]]++;
	for(i = head[s]; i != -1; i = edge[i].next){
        int v = edge[i].v;
        int flow = edge[i].flow;
        if (flow) {
            edge[i].flow -= flow;
			edge[i ^ 1].flow += flow;
            e[s] -= flow;
			e[v] += flow;
            if(v != s && v != t && !inq[v])
            {
                pq.push(v);
                inq[v]=1;
            }
        }
    }
	while (!pq.empty()) {
		int u = pq.top();
		pq.pop();
        inq[u] = 0;
		push_(u);
        if(e[u])
        {
            gap[h[u]]--;
            if(!gap[h[u]]){
                for(register int v = 1; v <= n; ++v){
                    if(v != s && v != t && h[v] > h[u] && h[v] < n+1){
                        h[v] = n + 1;
                    }
                }
            }
            relabel(u);
			gap[h[u]]++;
            pq.push(u);
			inq[u] = 1;
        }
	}
	return e[t];
}
//读入优化

int main() {
	//freopen("in.txt", "r", stdin);
	std::ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	memset(head, -1, sizeof(head));
	cin >> n >> m >> s >> t;
	register int i;
	int u, v, val;
	for(int i = 1; i <= m; ++i) cin >> u >> v >> val, addedge(u, v, val);
	printf("%d", Hlpp());
	return 0;
}

学习加强版 :待补。。。

发布了199 篇原创文章 · 获赞 156 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/Harington/article/details/100716130