题目描述
如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。
输入输出格式
输入格式:
第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来M行每行包含三个正整数ui、vi、wi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi)
输出格式:
一行,包含一个正整数,即为该网络的最大流。
输入输出样例
说明
时空限制:1000ms,128M
数据规模:
对于30%的数据:N<=10,M<=25
对于70%的数据:N<=200,M<=1000
对于100%的数据:N<=10000,M<=100000
题目中存在3条路径:
4-->2-->3,该路线可通过20的流量
4-->3,可通过20的流量
4-->2-->1-->3,可通过10的流量(边4-->2之前已经耗费了20的流量)
故流量总计20+20+10=50。输出50。
垃圾洛谷,花了一个下午学的预流推进跑的比Dinic还慢。我就不贴Dinic了,这里放一个预流推进:
#include<cstdio> #include<algorithm> #include<queue> using namespace std; const int maxn = 1e4 + 5; const int maxm = 1e5 + 5; struct edge { int v, w, next; }e[maxm << 1]; int head[maxn], cnt, n, m, s, t; void adde(const int &u, const int &v, const int &w) { e[++cnt] = (edge) {v, w, head[u]}, head[u] = cnt; e[++cnt] = (edge) {u, 0, head[v]}, head[v] = cnt; } struct node { int x, h; node(int rx, int rh) {x = rx, h = rh;} bool operator <(const node &a) const {return h < a.h;} }; namespace HLPP { const int inf = 0x3f3f3f3f; int pool[maxn], gap[maxn], h[maxn], N; priority_queue<node > q; int pushflow(int x, int y, int i) { int w = min(e[i].w, pool[x]); pool[x] -= w, pool[y] += w, e[i].w -= w, e[i ^ 1].w += w; return w; } void Sign(int mn, int s, int t) { for(register int i = 1; i <= N; ++i) if(h[i] > mn && i != s && i != t) h[i] = N + 1; } int maxflow(int n, int s, int t) { pool[s] = inf, N = h[s] = n, q.push(node(s, n)); while(!q.empty()) { int u = q.top().x, v; q.pop(); if(!pool[u]) continue; for(register int i = head[u]; i; i = e[i].next) { v = e[i].v; if((u == s || h[u] == h[v] + 1) && pushflow(u, v, i)) if(v != s && v != t) q.push(node(v, h[v])); } if(pool[u] && u != s && u != t) { if(!(--gap[h[u]])) Sign(h[u], s, t); ++gap[++h[u]], q.push(node(u, h[u])); } } return pool[t]; } } int main() { int a, b, c; scanf("%d%d%d%d", &n, &m, &s, &t), cnt = 1; for(register int i = 1; i <= m; ++i) { scanf("%d%d%d", &a, &b, &c); adde(a, b, c); } printf("%d", HLPP::maxflow(n, s, t)); return 0; }
没有帐号? 立即注册