【模板】网络最大流(EK、Dinic、ISAP)(网络流)/洛谷P3376

1|0题目链接

https://www.luogu.com.cn/problem/P3376

2|0题目大意

输入格式
第一行包含四个正整数 \(n,m,s,t\),分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来\(m\)行,每行包含三个正整数 \(u_i,v_i,w_i\),表示第 \(i\) 条有向边从 \(u_i\) 出发,到达 \(v_i\),边权为 \(w_i\)(即该边最大流量为 \(w_i\) )。
输出格式
一行,包含一个正整数,即为该网络的最大流。

3|0题目解析

(待补充,咕咕咕。。。)

4|0参考代码

\(EK\)

#include <bits/stdc++.h> using namespace std; const int N = 205; const long long INF = (1LL << 32); struct Edge{ int from, to; long long cap, flow; }; int n, m, s, t; long long a[N]; int p[N]; vector <Edge> e; vector <int> G[N]; void addEdge(int from, int to, int cap, int i) { e.push_back((Edge){from, to, cap, 0}); e.push_back((Edge){to, from, 0, 0}); G[from].push_back(i << 1); G[to].push_back((i << 1)+1); } long long maxflow() { long long flow = 0; while (1) { memset(a, 0, sizeof(a)); a[s] = INF; queue <int> q; q.push(s); while (!q.empty()) { int x = q.front(); q.pop(); for (int i=0; i<G[x].size(); ++i) { Edge &b = e[G[x][i]]; if (!a[b.to] && b.cap > b.flow) { p[b.to] = G[x][i]; a[b.to] = min(a[x], b.cap-b.flow); q.push(b.to); } } if (a[t]) break; } if (!a[t]) break; for (int u=t; u!=s; u=e[p[u]].from) { e[p[u]].flow += a[t]; e[p[u]^1].flow -= a[t]; } flow += a[t]; } return flow; } int main() { int u, v, w; scanf("%d%d%d%d", &n, &m, &s, &t); for (int i=0; i<m; ++i) { scanf("%d%d%d", &u, &v, &w); addEdge(u, v, w, i); } printf("%lld\n", maxflow()); return 0; }

\(Dinic\)

#include <bits/stdc++.h> #define ll long long using namespace std; const int INF = 2147483647; const int N = 205; struct Edge{ int from, to, cap, flow; }; int cur[N], depth[N]; int n, m, s, t; vector <Edge> e; vector <int> G[N]; void addEdge(int u, int v, int w, int i) { e.push_back((Edge){u, v, w, 0}); e.push_back((Edge){v, u, 0, 0}); G[u].push_back(i); G[v].push_back(i^1); } int BFS() { queue <int> Q; memset(depth, 0, sizeof depth); depth[s] = 1; Q.push(s); while (!Q.empty()) { int u = Q.front(); Q.pop(); for (int i = 0; i < G[u].size(); ++i) { Edge& b = e[G[u][i]]; if (!depth[b.to] && b.cap > b.flow) { depth[b.to] = depth[u] + 1; Q.push(b.to); } } } return depth[t]; } int DFS(int x, int a) { if (x == t || !a) return a; int flow = 0; for (int& i = cur[x]; i < G[x].size(); ++i) { Edge& b = e[G[x][i]]; if (depth[b.to] == depth[x]+1 && b.cap > b.flow) { if (int c = DFS(b.to, min(a, b.cap - b.flow))) { b.flow += c; e[G[x][i]^1].flow -= c; flow += c; a -= c; if (!a) break; } } } return flow; } ll maxFlow_Dinic() { ll ans = 0; while (BFS()) { memset(cur, 0, sizeof cur); ans += DFS(s, INF); } return ans; } int main() { scanf("%d%d%d%d", &n, &m, &s, &t); for (int i = 0; i < m; ++i) { int u, v, w; scanf("%d%d%d", &u, &v, &w); addEdge(u, v, w, i << 1); } printf("%lld\n", maxFlow_Dinic()); return 0; }

\(ISAP\)

#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 205; const int INF = 2147483647; struct Edge { int from, to, cap, flow; }; int n, m, s, t, cnt, gap[N], cur[N], dep[N]; vector <int> G[N]; vector <Edge> e; void addEdge(int u, int v, int w, int i) { e.push_back((Edge){u, v, w, 0}); e.push_back((Edge){v, u, 0, 0}); G[u].push_back(i); G[v].push_back(i^1); } void init() { memset(gap, 0, sizeof gap); memset(cur, 0, sizeof cur); memset(dep, 0, sizeof dep); ++gap[dep[t] = 1]; queue <int> Q; Q.push(t); while (!Q.empty()) { int x=Q.front(); Q.pop(); for (int i = 0; i < G[x].size(); i++) { int v = e[G[x][i]].to; if (!dep[v]) { ++gap[dep[v] = dep[x]+1]; Q.push(v); } } } } int augment(int x, int a) { if (x == t || !a) return a; int flow = 0; for (int &i=cur[x]; i < G[x].size(); i++) { Edge& b = e[G[x][i]]; if (dep[x] == dep[b.to] + 1 && b.cap > b.flow) { int tmp = augment(b.to, min(a, b.cap - b.flow)); flow += tmp; a -= tmp; b.flow += tmp; e[G[x][i]^1].flow -= tmp; if (!a) return flow; } } if (!(--gap[dep[x]])) dep[s] = cnt+1; ++gap[++dep[x]], cur[x] = 0; return flow; } ll maxFlow_ISAP() { cnt = n; //Num_of_nodes -> cnt init(); ll ans = 0; while (dep[s] <= cnt) ans += augment(s, INF); return ans; } int main() { scanf("%d%d%d%d", &n, &m, &s, &t); for (int i = 0; i < m; i++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); addEdge(u, v, w, i << 1); } printf("%lld\n", maxFlow_ISAP()); return 0; }

感谢支持!


__EOF__

本文作者炯炯目光
本文链接https://www.cnblogs.com/jjmg/p/13566795.html
关于博主:KTH 信息与网络工程硕士在读
版权声明:欢迎分享或转载
声援博主:To be or not to be, is a question.
posted @   Chiron-zy  阅读(184)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示