网络流-EK算法(保姆级教学)

本文引用董晓算法的部分图片。

一些不能带入纸质资料的竞赛,网络流纳入考纲。

因为需要默写,想来也不会考默写dinic这种算法难倒大家,只需要快速敲对EK算法就行了。

EK算法能在O(n*m^2)的复杂度内解决最大流问题,其中最大流就是源点到汇点的最大流量。

一般来说起点的流量是无穷,每条边有一个最大流容量c,再定义当前边已经流过了容量f。

很显然,网络流模型必须满足每条边的f<=c,同时每条边的流入量必须等于流出量。

EK算法的过程如下:

不断尝试,从源点找一条到达汇点流量大于0的路径,我们又称这条路为增广路

如图就是一条增广路。(图中5/5表示f/c)

但是确定一条增广路后,我们找新的增广路,就会因为旧的路径已经存在而被阻挡。

这时候我们就需要建立反向边。

反向边的意义在于给了之前存在的路径一个反悔的机会。

如图所示,假设右下角是汇点,左图是一条黑色的增广路,中间图片中,新增了一条红色的增广路,因为建立了反向边,所以红色路径可以正常到达汇点。等效成右图所示的结果,这样最大流就从5变成10了,其实就是通过反向边来达到旧边给新边让路的效果。

代码如下所示:

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e3+5;
int a[N][N];
int mf[N],isque[N];
//mf表示到该点的流量 
int pre[N];
int n,m,e;
int bfs(int su,int sv){
	memset(mf,0,sizeof(mf));
	for (int i=0;i<=n+m+1;i++) mf[i]=0;
	for (int i=0;i<=n+m+1;i++) isque[i]=0;
	mf[su]=INF;
	queue<int> q;
	q.push(su);
	isque[su]=true;
	pre[su]=-1;
	while(!q.empty()){
		int u=q.front();
		q.pop();
		isque[u]=false;
		for (int v=0;v<=n+m+1;v++){
			if (u==v) continue;
			if (mf[v]<min(mf[u],a[u][v])){
				mf[v]=min(mf[u],a[u][v]);
				pre[v]=u;
				if (mf[sv]!=0)	return true;
				if (isque[v]==false){
					q.push(v);
					isque[v]=true;
				}
			}
		}
	}
	return false;
}
int ek(int su,int sv){
	int ans=0;
	while(bfs(su,sv)){
		ans+=mf[sv];
		int p=sv;
		while(pre[p]!=-1){
			a[p][pre[p]]+=mf[sv];
			a[pre[p]][p]-=mf[sv];
			p=pre[p];
		}
	}
	return ans;
}
void work(){
	cin>>n>>m>>e;
	for (int i=1;i<=n;i++){
		a[0][i]=1;
		a[i][0]=0;
	}
	for (int i=1;i<=m;i++){
		a[i+n][n+m+1]=1;
		a[n+m+1][i+n]=0;
	}
	for (int i=1;i<=e;i++){
		int u,v;cin>>u>>v;
		a[u][v+n]=1;
		a[v+n][u]=0;
	}
	cout<<ek(0,n+m+1)<<"\n";
}
signed main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	work();
	return 0;
} 

其中用到了一个BFS和一个DFS(ek)。

BFS在不断找增广路(从源点找一条到达汇点流量大于0的路径),DFS把找到的增广路的流量确定下来,表示到边上,减少对应的容量,并给反向边增加相同的容量(能过去多少就能反悔多少)。

图的存储用邻接矩阵表示(反正都用EK算法了qwq,就更简单一点吧)。

BFS不断找增广路,其中套了一个SPFA的队列优化。mf数组表示到该点的流量为多少,因为需要不断找增广路,并把增广路得到的路径确定到边权的f(已经流过了容量),所以每次确定完成后mf数组就不再需要了,所以每次开始BFS之前要重新置为0。

其中有这个代码:

if (mf[v]<min(mf[u],a[u][v])){
    mf[v]=min(mf[u],a[u][v]);
}

mf[u]表示前面的点u最多给后面的点v多少流量,a[u][v]邻接矩阵表示这个管子最多承受多少流量,两者的较小值才是v点能过去的最大流量(此处贪心的想,因为要求最大流,所以肯定v点流量越大越好)

这里可能会有一个比较疑惑的点,那既然u到达了v,mf[v]更新了流量,为了满足每条边的流入量必须等于流出量,u点的mf数组不是应该更新吗?为什么代码里没有更新。如果不更新的话,假如mf[u]=5,岂不是u的每一个mf[v]都会被设置成5?

这是因为BFS的意义是找到一条可行的增广路,而不是真的全部遍历完才把结果抛给DFS。这样一旦有一条路径到达汇点,就一定仅仅只会有一条路径(感觉说了句废话),不会出现重复的情况。

这里可以发现mf的意义不是当前点的实际最大流,而是为了找到一条尽可能大且可行的流服务的。

感谢观看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/754728.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Flutter循序渐进==>封装、继承、多态、抽象类以及属性修改

导言 新学一门编程语言&#xff0c;最难以理解的莫过于类了。如果类没用&#xff0c;也就算了&#xff0c;它偏偏很有用&#xff0c;我们必须得掌握&#xff0c;不然怎么好意思说自己会面向对象编程呢? 抽象类&#xff08;Abstract Class&#xff09;在面向对象编程中扮演着…

如何看待AIGC中漫画版权争议?( 计育韬老师高校公益巡讲答疑实录2024)

这是计育韬老师第 8 次开展面向全国高校的新媒体技术公益巡讲活动了。而在每场讲座尾声&#xff0c;互动答疑环节往往反映了高校师生当前最普遍的运营困境&#xff0c;特此计老师在现场即兴答疑之外&#xff0c;会尽量选择有较高价值的提问进行文字答疑梳理。 *本轮巡讲主题除了…

java 操作 milvus 2.1.4

1. 确认 docker 运行的 milvus容器镜像版本情况&#xff1a; 2. pom 依赖&#xff1a; <dependency><groupId>io.milvus</groupId><artifactId>milvus-sdk-java</artifactId><version>2.1.0</version><exclusions><exclusi…

【秋招突围】2024届秋招笔试-科大笔试题-01-三语言题解(Java/Cpp/Python)

&#x1f36d; 大家好这里是清隆学长 &#xff0c;一枚热爱算法的程序员 ✨ 本系计划跟新各公司春秋招的笔试题 &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f497; 文章目录 &#x1f4d6…

在Tomcat中部署war包

1、准备war包 确保已经有一个有效的war包&#xff0c;该war包包含了web应用程序的所有内容&#xff1b; 2、停止tomcat服务器 在部署之前&#xff0c;确保tomcat服务器已经停止&#xff0c;进入tomcat的配置目录执行命令&#xff1a;[路径]/tomcat/conf&#xff1b; 在Linux…

前端vite+vue3——利用环境变量和路由区分h5、pc模块打包(从0到1)

⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享 前端vitevue3——利用环境变量和路由对前端区分h5和pc模块打包&#xff08;从0到1&#xff09;。 背景&#xff1a; 前端本地开发pc和h5的项目&#xff0c;发布时需要区分开h5和pc的页面 vite Vite 通过在一开始将应…

论文阅读--《FourierGNN:从纯图的角度重新思考多元时间序列预测》

Yi K, Zhang Q, Fan W, et al. FourierGNN: Rethinking multivariate time series forecasting from a pure graph perspective[J]. Advances in Neural Information Processing Systems, 2024, 36. 本次介绍的文章来自NeurIPS 2023&#xff0c;关于多变量时间序列的预测 摘要…

CocosCreator构建IOS的wwise教程

CocosCreator构建IOS教程 添加wwise教程: 1.添加include 2.添加SoundEngine 3.添加Profile-iphoneos下面lib下面的.a 4.导入js调用C++的文件 5.导入这些文件 6.初始化ios绝对路径和TTS语音合成对象 6.获得根目录绝对路径,加载pck需要找到绝对路径。怎么找绝对路径? #impor…

现如今软考通过率真的很低吗?

刚开始机考&#xff0c;10个人中有3个人表示想要尝试考试&#xff0c;这样通过率能高吗&#xff1f;就拿PMP证书来说吧&#xff0c;一下子就得花费三千多块&#xff0c;有几个人会轻易去尝试呢&#xff1f; 说到底&#xff0c;考试的难度是一个方面&#xff0c;考试的成本低是…

vue3日历选择器

倒叙日历&#xff1a; <template><div class"date-picker"><div class"column" wheel"onYearScroll"><div v-for"(year, index) in displayedYears" :key"index" :class"{current: year current…

深度解析RocketMq源码-消费者索引ConsumeQueue

1.绪论 rocketmq的broker中关于消息持久化的组件主要包含三个&#xff0c;分别是&#xff1a;持久化消息到文件中的组件commitLog&#xff1b;根据消息key索引commitLog日志的indexFile&#xff1b;消费者根据topic和queueId查询commitLog日志的consumeQueue。前面已经介绍com…

Profibus协议转profinet协议网关模块连接电机保护器与PLC通讯

一、背景 工业通讯中常见的协议有&#xff1a;Modbus协议&#xff0c;ModbusTCP协议&#xff0c;Profinet协议&#xff0c;Profibus协议&#xff0c;Profibus DP协议&#xff0c;EtherCAT协议&#xff0c;EtherNET协议等在现代工业控制系统中具有重要的角色。而Profibus协议转…

智慧数据中心可视化:高效管理与直观监控的未来

随着数据中心的规模和复杂性不断增加&#xff0c;传统管理方式难以满足需求。智慧数据中心通过图扑可视化实现实时数据监控和智能分析&#xff0c;将复杂的基础设施直观呈现&#xff0c;极大提升了运维效率、故障排查速度和资源优化能力&#xff0c;为企业提供现代化、智能化的…

mac app应用程序如何自定义图标, 更换.app为自己喜欢的图标或者图片 详细图文讲解

在mac系统中&#xff0c;我们可以对任何的app应用程序更换或者自定义图标&#xff0c; 这个图标可以是拥有的app的图标&#xff0c;或者是你自己制作的 x.icns 图标 或者是 任意的图片&#xff0c; 建议大小512x512 。 自定义图标方法如下&#xff1a; 1. 更换为已有app的图标…

词向量模型

文章目录 RNN词向量模型模型整体框架训练数据构建CBOW与Skip-gram模型负采样 RNN 卷积神经网络&#xff08;CNN&#xff09;主要应用计算机视觉&#xff0c;而递归神经网络&#xff08;RNN&#xff09;主要应用于自然语言处理。 递归神经网络会涉及处理之前所有的数据&#x…

Paragon NTFS与Tuxera NTFS有何区别 Mac NTFS 磁盘读写工具选哪个好

macOS系统虽然以稳定、安全系数高等优点著称&#xff0c;但因其封闭性&#xff0c;不能对NTFS格式磁盘写入数据常被人们诟病。优质的解决方案是使用磁盘管理软件Paragon NTFS for Mac&#xff08;点击获取激活码&#xff09;和Tuxera NTFS&#xff08;点击获取激活码&#xff0…

51单片机STC89C52RC——11.1 蜂鸣器播放音乐

目录 目的/效果 一&#xff0c;STC单片机模块 二&#xff0c;蜂鸣器 2.1 介绍 2.2 板子位置电路图 2.3 发声原理 2.4 音符和频率 三&#xff0c;创建Keil项目 四&#xff0c;代码 4.1 乐谱代码 4.1.1 《义勇军进行曲》 4.1.2 《天空之城》 4.1.3 《小美满》 4.1.…

2024年湖南建筑安全员考试题库,精准题库。

31.安全考核的对象应包括施工企业各管理层的&#xff08;&#xff09;、相关职能部门及岗位和工程项目参建人员。 A.技术负责人 B.安全负责人 C.主要负责人 D.第一负责人 答案&#xff1a;C 32.安全防护设施应标准化、定型化、&#xff08;&#xff09;。 A.规范化 B.工…

TFMath Caculator:一个简单的Java AWT计算器

目录 背景&#xff1a; 代码展示: 代码解析: 输出结果: 总结: 背景&#xff1a; 使用Java AWT(Abstract Window Toolkit)库创建的简单计算器应用-TFMath Calculator。这个计算器允许用户输入两个数字&#xff0c;点击号按钮后&#xff0c;计算器会计算这两个数字的和&…

【Redis四】主从复制、哨兵以及Cluster集群

目录 一.主从复制、哨兵、集群的区别 二.Redis主从复制 1.作用 2.原理 3.流程 三.搭建Redis 主从复制 1.源码编译安装以及配置文件修改 1.1.修改 Redis 配置文件&#xff08;Slave节点操作&#xff09; 2.验证主从复制 2.1.在Master节点上看日志 2.2.在Master节点上…