[luoguP3376] 网络最大流

题意

给出一个网络,求流量的最大值

sol

网络流板子题。
网络流是 OI 中比较常用的算法之一,以较高的建图难度深受出题人喜爱,不过近几年题目数量减少。
当然,在学习建图之前,需要先学会网络流的板子。

一些定义

(部分摘自 OI-Wiki)
网络是特殊的有向图 \(G=(V,E)\)
源点 \(s\) 是网络的起点,汇点 \(t\) 是网络的终点,\(s,t \in V\)
对于\(\forall (u,v) \in E\),其容量为 \(c(u,v)\),特别的,若 \((u,v) \notin E\)\(c(u,v) = 0\)
对于\(\forall (u,v) \in E\),其流量为 \(f(u,v)\),且满足以下性质:

  1. \(\forall (u,v) \in E, 0\le f(u,v) \le c(u,v)\)
  2. \(\forall u \in V - \{s,t\}, \sum_{x\in V} f(u,x) = \sum_{x\in V} f(x,u)\)

对于一个网络上的一个流,我们定义其流量 \(|f|=\sum_{x\in V} f(s,x) - \sum_{x\in V} f(x,s)\)
对于一个网络 \(G\),若 \(S\cap T=V\)\(S\cup T=\varnothing\)\(s \in S,t \in T\),则 {S,T} 是 \(G\) 的一个割,其容量 \(||S,T||=\sum_{u\in S}\sum_{v\in T} c(u,v)\)
对于网络 \(G\),其可能的最大的流量 \(f\) 即为 \(G\) 的最大流

Edmond-Karp

在残量网络中 BFS 找到一条增广路(从源点到汇点容量为正的路径),累加流量,最后更新残量网络。
理论复杂度上限 \(O(nm^2)\),实际可处理 \(10^3 \sim 10^4\) 的数据
代码:

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>using namespace std;
typedef unsigned int UI;
typedef long long LL;constexpr int N = 205, M = 10005;
constexpr UI INF = 1 << 31;int h[N], e[M], f[M], ne[M], idx;
int pre[N];
UI d[N];
bool st[N];
int n, m, S, T;void add(int a, int b, int c){e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx ++ ;
}bool BFS(){memset(st, false, sizeof st);queue<int> q;st[S] = true, d[S] = INF;q.push(S);while (!q.empty()) {int t = q.front();q.pop();for (int i = h[t]; ~i; i = ne[i]){int j = e[i];if (!st[j] && f[i]) {st[j] = true;pre[j] = i;d[j] = min(d[t], (UI) f[i]);if (j == T) return true;q.push(j);}}}return false;
}LL EK(){LL res = 0;while (BFS()) {res += d[T];for (int u = T; u != S; u = e[pre[u] ^ 1]) f[pre[u]] -= d[T], f[pre[u] ^ 1] += d[T];}return res;
}int main(){scanf("%d%d%d%d", &n, &m, &S, &T);memset(h, -1, sizeof h);while (m -- ){int a, b, c;scanf("%d%d%d", &a, &b, &c);add(a, b, c);}printf("%lld\n", EK());return 0;
}

Dinic

在残量网络中进行分层(防止出现环),然后爆搜每一条增广路,如果可行的话就累加
注意一部分优化:

  1. 在爆搜的过程中,如果发现当前节点的流出流量已经超过流入流量,则直接返回
  2. 在爆搜的过程中,如果发现某个节点无法提供任何流量,那么就在这个残量网络中删除这个节点
  3. 在爆搜的过程中,如果重复遍历某个点,那么继续上一次未搜索完的弧遍历(当前弧优化)

理论复杂度上限 \(O(n^2m)\),实际可处理 \(10^4 \sim 10^5\) 的数据。
代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>using namespace std;
typedef unsigned int UI;const int N = 1205, M = 240005;
const UI INF = 1 << 31;int h[N], e[M], ne[M], idx;
UI f[M];
int d[N], cur[N];
int n, m, S, T;void add(int a, int b, int c){e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx ++ ;
}bool bfs(){memset(d, -1, sizeof d);queue<int> q;q.push(S), d[S] = 0, cur[S] = h[S];while (!q.empty()) {int t = q.front(); q.pop();for (int i = h[t]; ~i; i = ne[i]){int j = e[i];if (d[j] == -1 && f[i]) {d[j] = d[t] + 1;cur[j] = h[j];if (j == T) return true;q.push(j);}}}return false;
}UI find(int u, UI limit) {if (u == T) return limit;UI flow = 0;for (int i = cur[u]; ~i && flow < limit; i = ne[i]){ // 优化 1cur[u] = i; // 优化 3int j = e[i];if (d[j] == d[u] + 1 && f[i]) {int t = find(j, min(limit - flow, f[i]));if (!t) d[j] = -1; // 优化 2f[i] -= t, f[i ^ 1] += t, flow += t;}}return flow;
}int dinic(){int res = 0, flow;while (bfs()) while (flow = find(S, INF)) res += flow;return res;
}int main(){scanf("%d%d%d%d", &n, &m, &S, &T);memset(h, -1, sizeof h);while (m -- ){int a, b, c;scanf("%d%d%d", &a, &b, &c);add(a, b, c);}printf("%d\n", dinic());
}

Dinic 算法在大部分题目中都够用,因为卡 Dinic 是没有浮木的行为。
此外还有效率差不多的 ISAP 算法和相对更快的 HLPP 算法(理论上届复杂度 \(O(n^2\sqrt{m})\)),但是不会。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/868208.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

idea设置快捷键

idea设置快捷键 下载安装idea 参考:pyhton、miniConda、pycharm下载安装配置中的pycharm下载安装配置即可,jetbrains系列软件都可如此操作。 查询快捷键 打开安装好的idea, ctrl+alt+s或手动打开Settings/设置, 点击左侧Keymap/按键映射页签, 点击右侧搜索框右侧的放大镜,…

抖音评论生成器在线工具,好评生成器软件,用js+html即可实现

开发技术HTML:用于搭建页面结构。 CSS:用于美化页面样式。 JavaScript:实现核心逻辑,包括文案生成、随机选择、复制功能等。 部分框架代码:<!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name=…

Odoo18.0附件分享管理

需求背景 虽然odoo官方提供了文档的门户访问功能,外部用户可以在门户查看共享的文档和相关的附件。但是某些情况下,我们希望外部用户只能有限地能访问我们指定的附件,而不是能够访问整个文档和全部附件。 本文即是介绍为了解决此问题而开发的功能。 功能介绍 这里我们以销售…

git worktree同一个仓库多个分支并行开发和管理

Git Worktree 是 Git 提供的一个功能,允许你在同一个仓库中同时工作在多个工作目录中,每个目录都有自己的工作树和索引。这对于同时处理多个分支或版本非常有用。介绍 Git Worktree 是 Git 提供的一个功能,允许你在同一个仓库中同时工作在多个工作目录中,每个目录都有自己的…

idea汉化教程,jetbrains系列软件都适用

idea汉化教程,jetbrains系列软件都适用 下载安装idea 参考:pyhton、miniConda、pycharm下载安装配置中的pycharm下载安装配置即可,jetbrains系列软件都可如此操作。 汉化 打开安装好的idea, ctrl+alt+s或手动打开Settings/设置, 点击左侧Plugins/插件页签, 点击右侧Market…

搭建jumpserver堡垒机--基本使用(三)

一.给所有服务器设置只允许jumpserver机器登录(尽量不要操作)1.开放堡垒机ssh登录,xxx.xxx.xxx.xxx对应堡垒机ipiptables -A INPUT -s xxx.xxx.xxx.xxx -p tcp --dport 22 -j ACCEPT2.拒绝所有机器ssh登录iptables -A INPUT -p tcp --dport 22 -j REJECT 二. 配置邮箱和创建用…

【学习笔记】斜率优化 dp

LearningForeword 斜率优化,顾名思义就是用一次函数的单调性来优化 dp,具体表现为利用单调性找到最优决策点从而优化掉需要枚举的决策点。 给斜率优化 dp 总结一个模板: \[dp_{i} = \min\{dp_{j} + calc (i,j)\} \]或者: \[dp_{i} = \max\{dp_{j} + calc (i,j)\} \]其中 \(…

安装MM系统(使用systemback封装Ubuntu系统iso镜像)

哈喽啊亲们!今天又是阳光明媚的一天,不知道亲们想me了没,今天小橘给大家分享一下MM系统镜像的封装流程,欢迎大家一起探讨。一、安装 MM 系统到其他机器的硬盘上 (一) BMC 挂载镜像 设置--一般--媒体重定向设置--一般设置--远程媒体支持--挂载 CD/DVD--填写信息--保存--选择…

【DMSQL系列】 达梦数据库写文件的方式探索

前沿 这篇文章整体算是🧲【DMSQL系列】SQL注入小记 的续集,达梦作为国内优秀的信创数据库,在关基单位中拥有越来越大的用户使用量。 通过SQL注入来写文件一直以来都是SQL注入漏洞深入利用的一种方式,对于不同的数据库通常写文件的方式也是不一样的。 通过笔者的探索发现,…

redis-shake工具同步redis数据

一、我的使用场景说明 1.业务场景由于业务要求,redis服务器迁移,将A服务器redis(单机)数据迁移到B服务器的redis(单机)上,只迁移5库数据,选择工具的原因是:B服务器上redis其他库都有数据,不能直接迁移A服务器redis的rdb或aof持久化文件 redis都是单机、6.0.2版本 red…

网站热门视频无法播放,如何解决?

针对您提到的网站热门视频无法播放的问题,我们可以从多个角度进行排查和解决。以下是一些建议,希望能帮助您快速找到问题所在并恢复正常播放功能。检查视频文件完整性:首先,请确认视频文件是否完整上传到了服务器。有时候由于网络波动或其他原因,可能导致文件传输过程中出…

服务器连接不上,如何排查和解决?

当您遇到服务器连接不上的问题时,首先需要明确具体的症状和环境。以下是详细的排查步骤和解决方案:确认网络连接:检查本地网络是否正常工作,尝试访问其他网站或服务,确保不是本地网络问题。 使用 ping 或 traceroute 命令测试与目标服务器的连通性。如果无法 ping 通,可能…