网络最大流(EK)
以前在oi中见到网络流的题都是直接跳过,由于本蒟蒻的理解能力太弱,导致网络流的学习不断推迟甚至被安排在了tarjan之后,原本计划于学习完最短路后就来学网络流的想法也随之破灭,在看完众多大佬
的博客后,我发现我不怎么能看懂(因为我自己太菜了),所以特来写一篇整理一下自己所学到的.
常见的网络流算法根据优化程度有FF<EK<Dinic<ISAP,由于后两种算法比较复杂,我至今也没有很好的理解,今天只要是我自己的一些对EK的理解.
首先需要了解一下什么是网络最大流:
网络流:所有弧上流量的集合f={f(u,v)},称为该容量网络的一个网络流.
定义:带权的有向图G=(V,E),满足以下条件,则称为网络流图(flow network):
- 仅有一个入度为0的顶点s,称s为源点
- 仅有一个出度为0的顶点t,称t为汇点
- 每条边的权值都为非负数,称为该边的容量,记作c(i,j)。
弧的流量:通过容量网络G中每条弧< u,v>,上的实际流量(简称流量),记为f(u,v);
网络流具有以下性质:
1.边所容纳的流量<=该边的最大容量.
2.反对称性,即f[u][v]=-f[v][u].
3.从源点流出的流量总是等于汇点汇聚的流量,对于其他的普通点来说,入度来的流量和等于出度出去的流量和.
最大网络流:网络流量图G中,最大的可行流称为网络最大流
我们定义:
源点:只有流出去的点
汇点:只有流进来的点
流量:一条边上流过的流量
容量:一条边上可供流过的最大流量
残量:一条边上的容量-流量
增广路:找到一条从源点到汇点的路径,使得路径上任意一条边的残量>0(注意是大于而不是大于等于,这意味着这条边还可以分配流量),这条路径便称为增广路
EK:不断找到一条起点到终点的路径,若有,找出这条路径上每一条边的最小值,然后将这条路上的每一条正向边减去这条路的流量,再在这条路上的每一条反向边加上这条边的流量,再在剩下的图上寻找新的路径,使总流量增加。然后形成新的图,再寻找新路径…..直到找不到从起点到终点的路径为止,最大流就算出来了。
#include<bits/stdc++.h>
using namespace std;
int st[],vis[],n,m,s,flow[],maxflow,t,x,y,z,tot=-,pre[],q[];
struct node
{
int from,to,val,last;
/*
from记录起点
to记录重点
val记录这条边的流量
last记录起点和当前这条边的起点一样的边的序号
*/
}e[];
int mn(int x,int y)
{
if(x>y)
return y;
return x;
}
void add(int f,int t,int v)
{//链式前向星
tot++;//当前这条边的序号
e[tot].from=f;
e[tot].to=t;
e[tot].val=v;
e[tot].last=st[f];
st[f]=tot;
return ;
}
bool bfs(int s,int m)//寻找从起点到终点的路径
{
int t=,h=;
for(int i=;i<=n;i++)
{
vis[i]=-;//一开始把所有的点(包括起点和终点)标志为没有走过
pre[i]=-;//记录上一条到达i点的边的起点的编号
}
t++;
q[t]=s;//将起点入队
vis[s]=;
flow[s]=;
while(t>=h)
{
int u=q[h];//拿出队首
vis[u]=;//当前的队首标志为不在队列里
h++;//踢出队首
for(int i=st[u];i!=;i=e[i].last)
{
int v=e[i].to;
if(e[i].val!= && vis[v]==-)//如果当前遍历到的点不在队列里(避免重复入队)就入队
{
flow[v]=mn(flow[u],e[i].val);//更新这条路径的流量(比较,求出最小值)
pre[v]=i;//编号为i的这条边到达了v点,更新pre[v]
t++;//入队
q[t]=v; //将
vis[v]=u;
}
}
}
if(vis[m]!=-)//从当前点s可以走到点m
return true;
return false;//如果运行到了这里,说明再也找不到从起点到终点的路了
}
void update(int s,int t)//一个回溯过程
{//如果能进这个函数,说明从当前点s可以走到点t
int now=t;//从终点往回查找
while(now!=s)//如果当前回溯到的点不是起点
{//继续找
int i=pre[now];
e[i].val-=flow[t];//正向边加上这条边的流量
e[i^].val+=flow[t];//建反向边,减去这条边的流量
now=e[i].from;//更新当前回溯到的点
}
maxflow+=flow[t];//加上当前这条边的流量
}
void EK(int s,int t)
{
maxflow=;//重置最大流
while(bfs(s,t)==true)//如果当前找得到一条从起点到终点的路
update(s,t);//加上这条路的流量
}
int main()
{
scanf("%d %d %d %d",&n,&m,&s,&t);
for(int i=;i<=m;i++)
{
scanf("%d %d %d",&x,&y,&z);
add(x,y,z);//建正向边
add(y,x,);//建反向边
}
EK(s,t);//求最大流
printf("%d",maxflow);//输出
return ;
}
网络最大流(EK)的更多相关文章
- 图论算法-网络最大流【EK;Dinic】
图论算法-网络最大流模板[EK;Dinic] EK模板 每次找出增广后残量网络中的最小残量增加流量 const int inf=1e9; int n,m,s,t; struct node{int v, ...
- 网络最大流算法—EK算法
前言 EK算法是求网络最大流的最基础的算法,也是比较好理解的一种算法,利用它可以解决绝大多数最大流问题. 但是受到时间复杂度的限制,这种算法常常有TLE的风险 思想 还记得我们在介绍最大流的时候提到的 ...
- luogu P3376 【模板】网络最大流(no)ek
题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行 ...
- 洛谷 P3376【模板】网络最大流
题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行 ...
- 网络最大流的(Edmond Karp)算法
容量网络:在有向图D=(V,A),指定一个点为发点,记作 s,指定另一个点为收点,记作 t,其余点叫作中间点.对于A的每条弧(Vi,Ai),都对应一个权数 C ≥0,称为弧(Vi , Ai)的容量,将 ...
- P3376 【模板】网络最大流(luogu)
P3376 [模板]网络最大流(luogu) 最大流的dinic算法模板(采取了多种优化) 优化 时间 inline+当前弧+炸点+多路增广 174ms no 当前弧 175ms no 炸点 249 ...
- 网络最大流算法—Dinic算法及优化
前置知识 网络最大流入门 前言 Dinic在信息学奥赛中是一种最常用的求网络最大流的算法. 它凭借着思路直观,代码难度小,性能优越等优势,深受广大oier青睐 思想 $Dinic$算法属于增广路算法. ...
- 『题解』洛谷P3376 【模板】网络最大流
Problem Portal Portal1:Luogu Description 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. Input 第一行包含四个正整数\(N,M,S,T\),分 ...
- 洛谷 P3376 【模板】网络最大流 题解
今天学了网络最大流,EK 和 Dinic 主要就是运用搜索求增广路,Dinic 相当于 EK 的优化,先用bfs求每个点的层数,再用dfs寻找并更新那条路径上的值. EK 算法 #include< ...
随机推荐
- 浅谈 OpenGL 中相关阻塞问题
昨天我遇到一个问题,问题如下: 我使用了延迟渲染,我的渲染流程是:Pass1 --> CUDA并行计算 -->Pass2 CUDA并行计算中需要使用Pass1渲染生成的两张纹理,然而我在G ...
- Python for Data Analysis 学习心得(四) - 数据清洗、接合
一.文字处理 之前在练习爬虫时,常常爬了一堆乱七八糟的字符下来,当时就有找网络上一些清洗数据的方式,这边pandas也有提供一些,可以参考使用看看.下面为两个比较常见的指令,往往会搭配使用. spli ...
- 24.python中xlwt模块用法详解
1.创建并保存一个excel 创建一个工作簿,设置编码格式为“utf-8”,默认格式是ASCII,为了方便写入中文,一般都要设置成UTF-8 import xlwt wb = xlwt.Workboo ...
- netcore 自动生成Dockerfile的坑
简介 之前采用shell脚本+dockerfile的方式构建项目,后来发现有Docker在17.05版本之后有多阶段构建方式,该文主要记录了netcore采用dockerfile构建遇到的坑. 原 ...
- ORA-00903表名无效关于${}和#{}的使用
相当于对数据 加上 双引号,$相当于直接显示数据 ${xxx}这样格式的参数会直接参与SQL编译,从而不能避免注入攻击 但可以使用在from之后传入表名 {}占位符? where之后 防止注入
- 利用SSH桥接访问服务器的Docker运行的MySql服务
前情提要 docker的运用越来广泛,许多IT公司都已经将自己的服务跑在Docker上面.在安全性方面又做了一层防护.比如:跑在Docker上的Mysql不做外网端口映射,只能在linux服务器上或进 ...
- AcWing 243. 一个简单的整数问题2 | 树状数组
传送门 题目描述 给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1.“C l r d”,表示把 A[l],A[l+1],…,A[r] 都加上 d. 2.“Q l r”,表示询问 ...
- 【转】20个简化开发任务的 JavaScript库
原文出处: codegeekz 译文出处: oschina 所谓JavaScript库就是预先写好的可以简化基于JavaScript的应用程序开发的,尤其是Ajax和其它以web为中心的技术的 J ...
- 第一篇博客-- 走上IT路
首先介绍一下本人,我是一名在校大学生,在一次学长分享学习经验时了解到,写博客可以帮助复习.所以这就是我要写博客的原因. 我是非常喜欢网络安全技术,因此我选择了我这个专业.在接下来的一段时间我会在这里记 ...
- 图解kubernetes调度器抢占流程与算法设计
抢占调度是分布式调度中一种常见的设计,其核心目标是当不能为高优先级的任务分配资源的时候,会通过抢占低优先级的任务来进行高优先级的调度,本文主要学习k8s的抢占调度以及里面的一些有趣的算法 1. 抢占调 ...