```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算法的更多相关文章

  1. (通俗易懂小白入门)网络流最大流——EK算法

    网络流 网络流是模仿水流解决生活中类似问题的一种方法策略,来看这么一个问题,有一个自来水厂S,它要向目标T提供水量,从S出发有不确定数量和方向的水管,它可能直接到达T或者经过更多的节点的中转,目前确定 ...

  2. 二分图的最大匹配——最大流EK算法

    序: 既然是个图,并且求边数的最大值.那么这就可以转化为网络流的求最大流问题. 只需要将源点与其中一子集的所有节点相连,汇点与另一子集的所有节点相连,将所有弧的流量限制置为1,那么最大流 == 最大匹 ...

  3. 最大流EK算法/DINIC算法学习

    之前一直觉得很难,没学过网络流,毕竟是基础知识现在重新来看. 定义一下网络流问题,就是在一幅有向图中,每条边有两个属性,一个是cap表示容量,一个是flow 表示流过的流量.我们要求解的问题就是从S点 ...

  4. 网络流最大流——dinic算法

    前言 网络流问题是一个很深奥的问题,对应也有许多很优秀的算法.但是本文只会讲述dinic算法 最近写了好多网络流的题目,想想看还是写一篇来总结一下网络流和dinic算法以免以后自己忘了... 网络流问 ...

  5. 初探网络流:dinic/EK算法学习笔记

    前记 这些是初一暑假的事: "都快初二了,连网络流都不会,你好菜啊!!!" from 某机房大佬 to 蒟蒻我. flag:--NOIP后要学网络流 咕咕咕------------ ...

  6. 最大流——EK算法

    一.算法理论 [基本思想] 反复寻找源点s到汇点t之间的增广路径,若有,找出增广路径上每一段[容量-流量]的最小值delta,若无,则结束.在寻找增广路径时,可以用BFS来找,并且更新残留网络的值(涉 ...

  7. [讲解]网络流最大流dinic算法

    网络流最大流算法dinic ps:本文章不适合萌新,我写这个主要是为了复习一些细节,概念介绍比较模糊,建议多刷题去理解 例题:codevs草地排水,方格取数 [抒情一下] 虽然老师说这个多半不考,但是 ...

  8. vector实现最大流EK算法

    序: 在之前的文章中实现了不利用STL实现EK算法,效率也较高.这次我们企图简化代码,减少变量的使用与手写模拟的代码. 注意:vector等STL的container在不开O2优化的时候实现同一个效果 ...

  9. HDU 1532 Drainage Ditches(最大流 EK算法)

    题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1532 思路: 网络流最大流的入门题,直接套模板即可~ 注意坑点是:有重边!!读数据的时候要用“+=”替 ...

  10. 【转】最大流EK算法

    转自:http://www.cnblogs.com/kuangbin/archive/2011/07/26/2117636.html 图-1 如图-1所示,在这个运输网络中,源点S和汇点T分别是1,7 ...

随机推荐

  1. 什么是 Gork ?

    Grok 是埃隆·马斯克旗下的人工智能公司 xAI 的开发的一系列大型语言模型 (LLMs)产品,包括Grok 1.Grok 2和即将发布的Grok 3. 受<银河系漫游指南>的启发,Gr ...

  2. DeepSeek 聊天机器人项目

    想要更深入玩转聊天机器人开发? 推荐本文档 + 课程<DeepSeek 聊天机器人项目>一起学习,效果翻倍! 边学边练,轻松打造智能对话系统~ (๑•̀ㅂ•́)و✧ 快上车,AI 之旅发车 ...

  3. 华为od机考2025A卷真题 -寻找重复代码

    题目描述与示例 题目 小明负责维护项目下的代码,需要查找出重复代码,用以支撑后续的代码优化,请你帮助小明找出重复的代码. 重复代码查找方法:以字符串形式给出两行代码text1,text2(字符串长度1 ...

  4. web自动化基础

    一.浏览器驱动 下载浏览器对应版本驱动 Chromedriver下载地址:https://npm.taobao.org/mirrors/chromedriver 下载谷歌对应版本对应系统的驱动,把下载 ...

  5. 1K star!这个开源项目让短信集成简单到离谱,开发效率直接翻倍!

    嗨,大家好,我是小华同学,关注我们获得"最新.最全.最优质"开源项目和高效工作学习方法 "让简单的事情回归简单的本质" -- SMS4J 项目宣言 SMS4J ...

  6. JavaScript中的DOM和Timer(简单易用的基本操作)

    JavaScript中的DOM和Timer基本操作 DOM操作 传统的选择器 选择器id var elements = document.getElementById(id的名称); 例如: var ...

  7. 【BUG】Python3|爬虫请求得到的json中的值全是问号

    如图: 原因:headers的"Accept":是text/html,application/xhtml+xml,application/xml;q=0.9,image/webp, ...

  8. Linux多线程-线程同步

    线程同步 当多个线程同时对一个共享数据进行操作时,会导致数据竞争,下面例子展示了数据竞争的情况: 1 #include <pthread.h> 2 #include <stdio.h ...

  9. 操作系统:设备I/O -- 如何表示设备类型与设备驱动?

    计算机的结构 计算机结构示意图: 主板上的各种芯片并非独立存在,而是以总线为基础连接在一起的,各自完成自己的工作,又能相互打配合,共同实现用户要求的功能. 如何管理设备 前面的学习中宏,实现了管理内存 ...

  10. C#中的i++,++i,i--,--i

    这些是 C# 中用于增加和减少变量值的运算符,下面是它们的用法: 1.i++ (后增量运算符):先使用变量 i 的当前值,然后将 i 的值加 1. int i = 0; int j = i++; // ...