网络流最大流EK算法
```cpp
/*
总的思路就是找还有哪些路可以走,只要找到新的路,流量就增加了
需要注意的是,这里面反向边的含义,可以大致理解为,找路的过程是随机的,可能找到的不是最优的,
那么,加一条反向边,后面就有可能找到这个反向边来走,这样就相当于弥补了以前的错误,相当于走了正确的道路
*/
#include <iostream>
using namespace std;
#include <cstring>
#include <algorithm>
#include <cstring>
#include <vector>
#include <iomanip>
#include <stdlib.h>
#include <unordered_map>
#include <queue>
typedef long long ll;
const int N = 100020, M = 2 * N;
struct Edge
{
ll v, c, ne;
} e[M]; // 存边的结构体,v表示边的终点,c表示剩下的容量,ne表示下一条边在边集中的位置
int idx = 1; /*这里之所以从1开始,是因为这里面要处理反向边,
我们为了方便找到一条边的反向边,
让正向边和对应的反向边在边集数组中相邻,两两配对
也就是add(a,b,c);紧接着add(b,a,0);反向边初始化为0
而我们在这里用i!=0来遍历边,所以0和1这一对就不能用了,
我们存边用e[++idx]={},这样从2和3开始配对
ps:相邻两个数(要求是偶数在前,奇数在后)满足:a^1=b,b^1=a,因为异或是不进位加法
*/
int h[N]; // 链表头节点指针数组,存储的是每个点的第一个出边在边集数组中的位置
int n, m;
int S, T; // 源点和汇点
ll mf[N]; // 从源点到v的路径上的流量上限
ll pre[N]; // 每个节点的前驱边在边集中的位置
void add(int a, int b, int c)
{
e[++idx] = {b, c, h[a]};
h[a] = idx;
}
bool bfs() // bfs找从源点到汇点的路径,如果能找到就返回true,否则返回false
{
memset(mf, 0, sizeof mf); // 初始化当前查找的路径的上,从源点到各个节点的流上限
// 同时mf还可以用来判断有没有被遍历
queue<int> q;
q.push(S); // 源点入队
mf[S] = 0x3f3f3f3f; // S到S的流量上限设为“无穷大”,不影响后面求流量上限
while (q.size())
{
auto u = q.front();
q.pop();
for (int i = h[u]; i; i = e[i].ne) // 遍历这个点的出边
{
ll v = e[i].v; // 取出这条边的重点
if (mf[v] == 0 && e[i].c) // 如果这个边的终点还没有被遍历,也就是这个边没有被遍历
//! 并且,这条边的容量还没有被用完,那就可以走这条边
{
mf[v] = min(mf[u], e[i].c); // 那么到v这个边的流量上限就是到u的流量上限和这条边的剩余容量的最小值
pre[v] = i; // 存储前驱边
q.push(v); // v入队
if (v == T)
{
// 如果找到了汇点,那就找到了一个可行的路径,直接返回true
return true;
}
}
}
}
return false;
}
ll EK() // 用于把可行的流量累加起来
{
ll flow = 0;
while (bfs()) // 每次先找一条可行的路径
{
// 如果还找的到
int v = T; // 从汇点反向找到源点,更新本次bfs找到的这条路径上各个边的剩余容量
while (v != S)
{
int i = pre[v]; // 找到这个点的前驱边
e[i].c -= mf[T]; // 从源点到汇点的流量上限就是这条路的流量
e[i ^ 1].c += mf[T]; // 给这个前驱边的反向边增加反向的流量,让后面的尝试可以选择把这条路退回来
v = e[i ^ 1].v; // 反向边的终点就是v的前驱点
}
flow += mf[T];
}
return flow;
}
int main()
{
cin >> n >> m >> S >> T;
for (int i = 1; i <= m; i++)
{
int a, b, c;
cin >> a >> b >> c;
add(a, b, c);
add(b, a, 0);
}
cout << EK();
return 0;
}
网络流最大流EK算法的更多相关文章
- (通俗易懂小白入门)网络流最大流——EK算法
网络流 网络流是模仿水流解决生活中类似问题的一种方法策略,来看这么一个问题,有一个自来水厂S,它要向目标T提供水量,从S出发有不确定数量和方向的水管,它可能直接到达T或者经过更多的节点的中转,目前确定 ...
- 二分图的最大匹配——最大流EK算法
序: 既然是个图,并且求边数的最大值.那么这就可以转化为网络流的求最大流问题. 只需要将源点与其中一子集的所有节点相连,汇点与另一子集的所有节点相连,将所有弧的流量限制置为1,那么最大流 == 最大匹 ...
- 最大流EK算法/DINIC算法学习
之前一直觉得很难,没学过网络流,毕竟是基础知识现在重新来看. 定义一下网络流问题,就是在一幅有向图中,每条边有两个属性,一个是cap表示容量,一个是flow 表示流过的流量.我们要求解的问题就是从S点 ...
- 网络流最大流——dinic算法
前言 网络流问题是一个很深奥的问题,对应也有许多很优秀的算法.但是本文只会讲述dinic算法 最近写了好多网络流的题目,想想看还是写一篇来总结一下网络流和dinic算法以免以后自己忘了... 网络流问 ...
- 初探网络流:dinic/EK算法学习笔记
前记 这些是初一暑假的事: "都快初二了,连网络流都不会,你好菜啊!!!" from 某机房大佬 to 蒟蒻我. flag:--NOIP后要学网络流 咕咕咕------------ ...
- 最大流——EK算法
一.算法理论 [基本思想] 反复寻找源点s到汇点t之间的增广路径,若有,找出增广路径上每一段[容量-流量]的最小值delta,若无,则结束.在寻找增广路径时,可以用BFS来找,并且更新残留网络的值(涉 ...
- [讲解]网络流最大流dinic算法
网络流最大流算法dinic ps:本文章不适合萌新,我写这个主要是为了复习一些细节,概念介绍比较模糊,建议多刷题去理解 例题:codevs草地排水,方格取数 [抒情一下] 虽然老师说这个多半不考,但是 ...
- vector实现最大流EK算法
序: 在之前的文章中实现了不利用STL实现EK算法,效率也较高.这次我们企图简化代码,减少变量的使用与手写模拟的代码. 注意:vector等STL的container在不开O2优化的时候实现同一个效果 ...
- HDU 1532 Drainage Ditches(最大流 EK算法)
题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1532 思路: 网络流最大流的入门题,直接套模板即可~ 注意坑点是:有重边!!读数据的时候要用“+=”替 ...
- 【转】最大流EK算法
转自:http://www.cnblogs.com/kuangbin/archive/2011/07/26/2117636.html 图-1 如图-1所示,在这个运输网络中,源点S和汇点T分别是1,7 ...
随机推荐
- 要命的DRG成本核算!
改开几十年的三座大山之一,鬼见愁的问题.会随着DRG的推进而让平头老百姓过上翻身做主的日子呢!? 对于DRG,首先医保部门需要了解病种成本状况,确定给你结算多少银子.第二,咱们医院靠医保吃饭,那就更需 ...
- Spring框架中的单例bean是线程安全的吗?
1.介绍两个概念 有状态的bean:对象中有实例变量(成员变量),可以保存数据,是非线程安全的 无状态的bean:对象中没有实例变量(成员变量),不能保存数据,可以在多线程环境下共享,是线程安全的 2 ...
- Java 21 新特性
Java 21 是 Java 语言的一次重要更新,引入了若干新的特性,提升了开发者的编程效率和代码质量.本文将详细介绍 Java 21 的新特性,包括基础概念.使用方法.常见实践以及最佳实践. 简介 ...
- 话说神奇的content="IE=edge,chrome=1"的meta标签内容
这是个是IE8的专用标记,用来指定IE8浏览器去模拟某个特定版本的IE浏览器的渲染方式(比如人见人烦的IE6),以此来解决部分兼容问题,例如模拟IE7的具体方式如下: < meta http-e ...
- Git常用命令大全:git命令基本用法
1. 常用的git命令 Git 常用的六个命令是什么? ·"git clone"克隆代码: ·"git log"查看日志: ·"git tag&quo ...
- Python实验2 turtle 库绘制进阶图形
实验任务: 绘制嵌套彩色五角星(大小逐层递减) 设计函数绘制自定义正多边形(边数与颜色参数化) 扩展:实现动态旋转花瓣图案. 源代码:import turtle 绘制嵌套彩色五角星 def neste ...
- CTF你真的懂PHP吗--PHP代码审计
http://ctf5.shiyanbar.com/web/PHP/index.php 就是一个纯代码审计 访问.txt地址撸一把源码 进行分析 <?php $info = "&quo ...
- 使用DVC管理大文件变更历史(基于git)
DVC(Data Version Control) 是一个专门用于管理数据和二进制文件版本控制 的工具,它特别适合那些需要处理大量非文本文件(如图像.视频.模型.数据集等)的项目. 一般地,如果项目中 ...
- Gnirehtet —— 通过 USB 让手机共享 PC 网络
Gnirehtet 使用教程 什么是 Gnirehtet? Gnirehtet("Tethering" 反写)是 Google 开发的开源工具,用于 通过 USB 共享 PC 网络 ...
- 制作带sshd功能的centos镜像
docker run -it --name node1 docker.io/centos bash 创建node1容器 docker exec -it node1 bash 进入node1 yum ...