当前位置: 首页 > backend >正文

LG P4722 LOJ 127 【模板】最大流 加强版 Solution

Description

给定一个 n n n m m m 边的有向网络图,求 s s s t t t 的最大流.

Limitations

1 ≤ n ≤ 1200 1\le n\le 1200 1n1200
1 ≤ m ≤ 1.2 × 1 0 5 \textcolor{red}{1\le m\le 1.2\times 10^5} 1m1.2×105
1 ≤ u , v , s , t ≤ n 1\le u,v,s,t\le n 1u,v,s,tn
1 ≤ w < 2 31 1\le w<2^{31} 1w<231
1.5 s , 500 MB (on luogu) 1.5\text{s},500\text{MB}\;\texttt{(on luogu)} 1.5s,500MB(on luogu)

Solution

其实不需要 HLPP.
Dinic 在边权差距小的时候跑得较快,所以我们进行分组,对每个 i ∈ [ 0 , 31 ) i\in[0,31) i[0,31),将 w ∈ [ 2 i , 2 i + 1 ) w\in[2^i,2^{i+1}) w[2i,2i+1) 的边分为一组,从大到小对,对每组分别跑 Dinic,可以显著加快速度.(跑完的边和下一组一起跑)

但这样还不够,注意到反向边会拖慢 Dinic 速度(因为会退回输送过去的流量).
对于每组,我们可以先只加正向边跑一遍 Dinic(但是要更新反向边的流量).
然后在残量网络上一次性加入所有反向边,再跑一遍 Dinic 即可求出正确答案.

效率再次提升,可以通过此题,时间复杂度玄学.

Code

3.69 KB , 2.77 s , 5.15 MB (in total, C++20 with O2) 3.69\text{KB},2.77\text{s},5.15\text{MB}\;\texttt{(in total, C++20 with O2)} 3.69KB,2.77s,5.15MB(in total, C++20 with O2)(on luogu)
最大流板子需要修改一处(先不加反向边),板子其他部分省略.

#include <bits/stdc++.h>
using namespace std;using i64 = long long;
using ui64 = unsigned long long;
using i128 = __int128;
using ui128 = unsigned __int128;
using f4 = float;
using f8 = double;
using f16 = long double;template<class T>
bool chmax(T &a, const T &b){if(a < b){ a = b; return true; }return false;
}template<class T>
bool chmin(T &a, const T &b){if(a > b){ a = b; return true; }return false;
}template<class T>
struct MaxFlow {// ......void addEdge(int u, int v, T c) {g[u].push_back(e.size());e.emplace_back(v, c);// g[v].push_back(e.size());     // 暂时不加反向边e.emplace_back(u, 0);}// ......
};
using Edge = array<int, 3>;signed main() {ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int n, m, s, t;scanf("%d %d %d %d", &n, &m, &s, &t), s--, t--;vector<Edge> e(m);for (auto & [u, v, w] : e) scanf("%d %d %d", &u, &v, &w), u--, v--;sort(e.begin(), e.end(), [&](const Edge& a, const Edge& b) { return a[2] > b[2]; });MaxFlow<int> g(n);int ans = 0;for (int tp : {0, 1}) for (int p = 1 << 30, i = 0; p; p /= 2) {while (i < m && e[i][2] >= p) { auto [u, v, w] = e[i];if (tp == 1) g.g[v].push_back(i * 2 + 1);else g.addEdge(u, v, w);i++;}ans += g.flow(s, t);}printf("%d\n", ans);return 0;
}
http://www.xdnf.cn/news/7115.html

相关文章:

  • C语言练手磨时间
  • 编程速递:适用于 Delphi 12.3 的 FMX Linux 现已推出
  • C++面试2——C与C++的关系
  • 12.输出常量的两个小扩展
  • leetcode hot100刷题日记——2.字母异位词分组
  • 【第三篇】 SpringBoot项目中的属性配置
  • 中科院自动化研究所通用空中任务无人机!基于大模型的通用任务执行与自主飞行
  • Linux的内存泄漏问题及排查方法
  • 记录一次win11本地部署deepseek的过程
  • linux-----------------库制作与原理(下)
  • 宝塔9.6.0python项目程序运行卡住bug解决方案
  • mvc-ioc实现
  • 游戏引擎学习第291天:跳跃的怪物与占据的树木
  • Google aab包转成apk,并安装到手机设备中
  • 77.数据大小端赋值的差异与联系
  • 华为云Astro中各种变量与参数的区别与用法
  • C 语言字符串输入输出:scanf, gets, fgets 的选择与陷阱
  • Word文档图片和图表自动添加序号
  • 基于区块链技术的供应链溯源系统:重塑信任与透明度
  • 信奥赛-刷题笔记-栈篇-T2-P3056括号调整问题0518
  • Android日活(DAU)检测的四大实现方案详解
  • 代码随想录算法训练营 Day49 图论Ⅰ 深度优先与广度优先
  • mongodb管理工具的使用
  • 几种基于比较的排序
  • Linux搜索
  • 初始C++:类和对象(中)
  • 第10章 输入与输出流
  • Ansible模块——文件内容修改
  • IntelliJ IDEA设置编码集
  • ngx_http_referer_module 模块概述