网络流最大流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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
· 什么是nginx的强缓存和协商缓存
· 一文读懂知识蒸馏