网络流最大流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 ...
随机推荐
- 【Ubuntu】ARM交叉编译开发环境解决“没有那个文件或目录”问题
[Ubuntu]ARM交叉编译开发环境解决"没有那个文件或目录"问题 零.起因 最近在使用Ubuntu虚拟机编译ARM程序,解压ARM的GCC后想要启动,报"没有那个文件 ...
- MySQL 的默认字符集为什么是 latin1?
是处于历史原因还是其他? 为什么至今不选择utf-8? West European Character Sets
- 使用Nginx反向代理本地服务(无固定公网IP通过端口映射公开的服务)的坑
使用Nginx反向代理本地服务(无固定公网IP通过端口映射公开的服务)的坑 前言:之前公司的服务器都是云服务器,性能比较差,而我们有一些内部使用的系统和极少数外部用户使用的系统,对资源有一定的要求,也 ...
- Model Context Protocol
MCP is an open protocol that enables AI models to securely interact with local and remote resources ...
- lua三色标记的读写屏障理解
起因是已经被标记为黑色的对象无法进行再次遍历,然而黑色对象发生了引用变化:断开了引用或者引用了别的对象,会导致多标(不再被黑色对象引用的对象未能回收),漏标(黑色对象的新引用未能遍历标记)
- dubbo源码解析-服务暴露与发现
一.概述 dubbo是一个简单易用的RPC框架,通过简单的提供者,消费者配置就能完成无感的网络调用.那么在dubbo中是如何将提供者的服务暴露出去,消费者又是如何获取到提供者相关信息的呢? 二.dub ...
- jmeter返回数据重新编码的方法
下图内容为请求后的返回值,红色箭头内容是需要正则处理传参给后面的接口使用 其中==后面的\U0026为未编码内容 而实际能够提交的链接为下图"&" 所以,图1请求后需要先转 ...
- 为什么 Java 新生代被划分为 S0、S1 和 Eden 区?
为什么 Java 新生代被划分为 S0.S1 和 Eden 区? 在 Java 的 垃圾回收(GC)机制中,新生代 被进一步划分为 Eden 区 和两个 Survivor 区(S0 和 S1).这种划 ...
- [设计模式/Java] 设计模式之门面模式(外观模式)【20】
概述 : 门面模式 := 外观模式 := Facade Pattern 产生背景 软件开发过程中,我们经常会遇到复杂系统,其中包含多个子系统和接口.在这种情况下,为了简化客户端的调用过程,提高代码的可 ...
- Asp.net core 少走弯路系列教程(三)CSS 学习
前言 新人学习成本很高,网络上太多的名词和框架,全部学习会浪费大量的时间和精力. 新手缺乏学习内容的辨别能力,本系列文章为新手过滤掉不适合的学习内容(比如多线程等等),让新手少走弯路直通罗马. 作者认 ...