图论 —— 网络流 —— 最大流 —— FF 算法与 EK 算法
【概述】
FF 算法与 EK 算法是求解最大流的一般增广路方法,其时间复杂度均为 O(n*m*m)
Ford-Fulkerson 算法是求解最大流的最基础的算法,其核心思想是增广路定理:网络达到最大流当且仅当残留网络中没有增广路
程序的实现过程与增广路求最大流的过程基本一致,即每一次更新都进行一次找增广路然后更新路径上的流量的过程。
在传统的 FF 算法中,利用 dfs 每次找增广路的过程十分繁琐,常常会走冤枉路,此时更新增广路的复杂度就会增加,EK 算法为了规避这个问题使用了 bfs 来寻找增广路,然后在寻找增广路的时候总是向离汇点越来越近的方向去寻找下一个结点。
【基本思想】
1)若存在增广路径,则找出一条增广路径(通过 BFS)
2)沿着找出的增广路径进行更新流量
3)当没有增广路时,网络达到最大流
【沿增广路径增广方法】
第一步:计算可增加流量
设:某一增广路径结点为 a1,a2,...,an,可增加流的增加流量 dis=INF
若 (u,v) 是正向边,则:dis=min(dis,c(ai,aj)-f(ai,aj)),其中:j=i+1,i=1,2,...,n-1
若 (u,v) 是逆向边,则:dis=min(dis,f(ai,aj)),其中:j=i+1,i=1,2,...,n-1
第二步:更新流量
若 (u,v) 是正向边,则:f(u,v)=f(u,v)+dis
若 (u,v) 是负向边,则:f(u,v)=f(u,v)-dis(伴随着这部分流量的减去,必有另一部分的管道流量会增加)
【模版】
1.FF 算法
struct Edge {int to, next;int cap;
} edge[N * N];
int head[N], tot;
bool vis[N], flag;
LL res;
void addEdge(int x, int y, int cap) {edge[tot].to = y;edge[tot].cap = cap;edge[tot].next = head[x];head[x] = tot++;edge[tot].to = x;edge[tot].cap = 0;edge[tot].next = head[y];head[y] = tot++;
}
int dfs(int x, int T, int flow) { // dfs求任意路径if (x == T) {res += flow;flag = true;return flow;}vis[x] = true;for (int i = head[i]; i != -1; i = edge[i].next) {int x1 = edge[i].to;if (vis[x1] || edge[i].cap == 0)continue;int newFlow = dfs(x1, T, min(flow, edge[i].cap));if (flag) {edge[i].cap -= newFlow;edge[i ^ 1].cap += newFlow;return newFlow;}}return 0;
}
void FF(int S, int T) { //有增广路就增广flag = 0;memset(vis, 0, sizeof(vis));dfs(S, T, INF);while (flag) {flag = 0;memset(vis, 0, sizeof(vis));dfs(S, T, INF);}
}
int main() {memset(head, -1, sizeof(head));tot = 0;res = 0;int n, m;scanf("%d%d", &n, &m);for (int i = 1; i <= m; i++) {int x, y, cap;scanf("%d%d%d", &x, &y, &cap);addEdge(x, y, cap);}int S = 1, T = n;FF(S, T);printf("%d\n", res);return 0;
}
2.EK 算法
int n, m;
int cap[N][N]; //容量
int flow[N][N]; //流量int EK(int s, int t) { //沿着增广路增广int res = 0; //最大流int dis[N]; // a[i]表示从s到i的最小残量int p[N]; //增广路中的上一节点queue<int> Q;while (true) {memset(dis, 0, sizeof(dis));dis[s] = INF;Q.push(s);//计算可增加流量while (!Q.empty()) {int x = Q.front();Q.pop();for (int y = 1; y <= n; y++) {if (!dis[y] && cap[x][y] > flow[x][y]) {p[y] = x;Q.push(y);dis[y] = min(dis[x], cap[x][y] - flow[x][y]);}}}if (dis[t] == 0) //当网络中没有增广路径break;//更新流量for (int x = t; x != s; x = p[x]) {flow[p[x]][x] += dis[t];flow[x][p[x]] -= dis[t];}res += dis[t];}return res; //返回最大流
}int main() {int n, m;scanf("%d%d", &n, &m);memset(cap, 0, sizeof(cap));memset(flow, 0, sizeof(flow));while (m--) {int x, y, w;scanf("%d%d%d", &x, &y, &w); //两点的容量cap[x][y] = +w; //可能有重边}printf("%d\n", EK(1, n));return 0;
}
图论 —— 网络流 —— 最大流 —— FF 算法与 EK 算法相关推荐
- 图论 —— 网络流 —— 最大流 —— Dinic 算法
[概述] Dinic 算法在 EK 算法的基础上进行了优化,其时间复杂度为 O(n*n*m). Dinic 在找增广路的时也是找最短增广路, 但与 EK 算法不同的是 Dinic 算法并不是每次 bf ...
- 图论-网络流⑦-费用流解题
图论-网络流⑦-费用流解题 上一篇:图论-网络流⑥-费用流 下一篇:图论-网络流⑧-有上下界的网络流 参考文献: https://www.luogu.com.cn/blog/user9012/solu ...
- 最大流算法之一——EK算法
EK算法流程 EK算法的流程很简单: 随意找一个可行流作为流量网络更新的基础(一般题目没有规定可以采用流量为0的可行流) 利用bfsbfsbfs找一条从源点到汇点的可行流路径 用新找到的可行流路径更新 ...
- 图论 —— 网络流 —— 最大流 —— 压入与重标记算法
[概述] 压入与重标记算法(Push-Relable Algorithms)又称预留推进算法,是 GoldBerg 与 Tarjan 共同发现的,时间复杂度为 O(V*V*E) 该算法与 EK .Di ...
- 图论 —— 网络流 —— 费用流 —— MCMF 算法
[概述] EK 算法是每次用广搜寻找一条最短的增广路,然后沿其增广,而 MCMF 算法是在 EK 算法的基础上,每次用 SPFA 计算图的距离标号,然后沿着可行边进行增广,即将 EK 算法中的 bfs ...
- 图论 —— 网络流 —— 费用流 —— zkw 费用流
[概述] 求解费用流的方法很多,目前最流行的是 MCMF 费用流,其实质是将 EK 算法中的 bfs 换为了 SPFA 来计算最小费用,但其存在的一个缺点是 EK 是单路增广的,这样速度会相应的慢一些 ...
- 图论 —— 网络流 —— 费用流 —— 基于 Dijkstra 的费用流
[概述] 在求解费用流时,大多数情况都是使用基于 SPFA 的 MCMF 算法,但有时某些毒瘤题会卡 SPFA,此时就要利用基于 Dijkstra 的费用流来求解. [算法原理] 基于 Dijkstr ...
- 图论--网络流--最大流 洛谷P4722(hlpp)
题目描述 给定 nn 个点,mm 条有向边,给定每条边的容量,求从点 ss 到点 tt 的最大流. 输入格式 第一行包含四个正整数nn.mm.ss.tt,用空格分隔,分别表示点的个数.有向边的个数.源 ...
- Edmonds-Karp算法(EK算法)简单讲解及实现(邻接表)
目录 最大流问题介绍 图定义 源点与汇点 最大流问题描述 Ford-Fulkerson方法 回退边与增广图 伪代码 图解 Edmonds-Karp算法 复杂度 代码实现细节 代码 最大流问题介绍 图定 ...
最新文章
- package和import语句_5
- apt和apt-get的区别?为什么推荐使用apt?RedHat系列(rpm包、包管理工具yum)和Debian系列(deb包、包管理工具apt-get)区别?
- c++ 6.0 没有找到mspdb60.dll 问题的解决
- SAP CRM IPC and configuration page debugs
- 从钱龙数据中读取股票权息信息导入到数据库
- c语言水仙花验证,[编程入门]水仙花数判断 (C语言代码)
- 9招让你皮肤迅速白嫩 - 健康程序员,至尚生活!
- dedecms 模型新添加的自定义字段设置样式
- Linux内核Makefile编译生成内核目标文件的过程
- 430单片机实现三人投票表决器_关于STC51下载器串口免冷启动简单方案
- 明翰恶意软件分析笔记V0.1(持续更新)
- Jenkins的定时构建与轮询SCM
- pdfbox创建pdf_使用PDFBox处理PDF文档(新建PDF文件、修改PDF文件、PDF中插入图片、将PDF文件转换为图片)...
- 计算机打印机驱动f4200,惠普HP Deskjet F4238 多功能一体机驱动惠普HP Deskjet F4238 多功能一体机驱动...
- 京东登录界面html css,css制作京东登录页面 css样式,京东店面装修怎么写CSS样式?...
- 2008服务器远程开启,windows server 2008 r2中开启远程桌面的方法
- W806串口管脚复用
- Qt 数字报阅读器 图文版
- Canny算子中的梯度求取及非最大值抑制(NMS)实现
- 微信小程序api记载
热门文章
- 数据中台VS业务中台、数据中台VS数据仓库,到底有什么区别?
- 从数据泄露到大数据杀熟,互联网未来路在何方?
- Simulink之变压器漏抗对整流电路的影响
- 周末给女友讲了遍加密算法,没想到...
- 排查 Linux 系统故障,看这一篇足够了。
- PaaS中OpenShift持久化存储的管理实践
- JEECG_3.7 权限开发视频正式发布
- JEECG开源说明:JEECG 完全开源,不收任何费用,可以任用于商业!
- SpringBoot2.0 基础案例(16):配置Actuator组件,实现系统监控
- 华为云TaurusDB性能挑战赛-java赛题mvn编译时报错:不支持 diamond 运算符