以前在oi中见到网络流的题都是直接跳过,由于本蒟蒻的理解能力太弱,导致网络流的学习不断推迟甚至被安排在了tarjan之后,原本计划于学习完最短路后就来学网络流的想法也随之破灭,在看完众多大佬

的博客后,我发现我不怎么能看懂(因为我自己太菜了),所以特来写一篇整理一下自己所学到的.

常见的网络流算法根据优化程度有FF<EK<Dinic<ISAP,由于后两种算法比较复杂,我至今也没有很好的理解,今天只要是我自己的一些对EK的理解.

首先需要了解一下什么是网络最大流:

网络流:所有弧上流量的集合f={f(u,v)},称为该容量网络的一个网络流.

  • 定义:带权的有向图G=(V,E),满足以下条件,则称为网络流图(flow network):

    1. 仅有一个入度为0的顶点s,称s为源点
    2. 仅有一个出度为0的顶点t,称t为汇点
    3. 每条边的权值都为非负数,称为该边的容量,记作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)的更多相关文章

  1. 图论算法-网络最大流【EK;Dinic】

    图论算法-网络最大流模板[EK;Dinic] EK模板 每次找出增广后残量网络中的最小残量增加流量 const int inf=1e9; int n,m,s,t; struct node{int v, ...

  2. 网络最大流算法—EK算法

    前言 EK算法是求网络最大流的最基础的算法,也是比较好理解的一种算法,利用它可以解决绝大多数最大流问题. 但是受到时间复杂度的限制,这种算法常常有TLE的风险 思想 还记得我们在介绍最大流的时候提到的 ...

  3. luogu P3376 【模板】网络最大流(no)ek

    题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行 ...

  4. 洛谷 P3376【模板】网络最大流

    题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行 ...

  5. 网络最大流的(Edmond Karp)算法

    容量网络:在有向图D=(V,A),指定一个点为发点,记作 s,指定另一个点为收点,记作 t,其余点叫作中间点.对于A的每条弧(Vi,Ai),都对应一个权数 C ≥0,称为弧(Vi , Ai)的容量,将 ...

  6. P3376 【模板】网络最大流(luogu)

    P3376 [模板]网络最大流(luogu) 最大流的dinic算法模板(采取了多种优化) 优化 时间 inline+当前弧+炸点+多路增广 174ms no 当前弧 175ms no 炸点 249 ...

  7. 网络最大流算法—Dinic算法及优化

    前置知识 网络最大流入门 前言 Dinic在信息学奥赛中是一种最常用的求网络最大流的算法. 它凭借着思路直观,代码难度小,性能优越等优势,深受广大oier青睐 思想 $Dinic$算法属于增广路算法. ...

  8. 『题解』洛谷P3376 【模板】网络最大流

    Problem Portal Portal1:Luogu Description 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. Input 第一行包含四个正整数\(N,M,S,T\),分 ...

  9. 洛谷 P3376 【模板】网络最大流 题解

    今天学了网络最大流,EK 和 Dinic 主要就是运用搜索求增广路,Dinic 相当于 EK 的优化,先用bfs求每个点的层数,再用dfs寻找并更新那条路径上的值. EK 算法 #include< ...

随机推荐

  1. Okhttp解析—Okhttp概览

    Okhttp解析-Okhttp概览 Okhttp作为目前Android使用最为广泛的网络框架之一,我们有必要去深入了解一下,本文是Okhttp解析的第一篇,主要是从宏观上认识Okhttp整个架构是如何 ...

  2. Cocos Creator | 飞刀大乱斗开发教程系列(三)

    预览效果 ​ 具体内容 ■ 这一期,主要讲解游戏过程中,通过触摸滑动,控制人物的运动方向,以及游戏过程中,人物运动区域的控制.如下图,人物通过滑动控制运动方向,即是往哪个方向滑动,人物就往哪个方向移动 ...

  3. leetcode腾讯精选练习之两数相加

    两数相加 题目: 给出两个非空的链表用来表示两个非负的整数.其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字.如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们 ...

  4. 【记】创建 VirtualBoxClient COM 对象失败. 应用程序将被中断

    1. 在本地64位win7系统安装VirtualBox完,启动时提示错误 原因:兼容性造成的 按照下图显示修改VirtualBox快捷方式的兼容性 2. 启动虚拟机时,提示 点击弹出框的确定按钮后,接 ...

  5. Android Studio build不显示Generate signed apk问题

    如果是刚装的AS,那么新建一个项目,进入项目后,会发现build选项卡缺了一些选项,同时底部sync在转圈圈,其实是AS在自动下载gradle,也许还在下载build-tools,我等了11分钟才结束 ...

  6. 5、调试显示应该使用 DebuggerDisplay 而不是误用 ToString

    using System.Diagnostics; namespace ShouldCode.Console { [DebuggerDisplay("Prop1:{Prop1};Prop2: ...

  7. hive 动态分区

    非常重要的动态分区属性: hive.exec.dynamic.partition  是否启动动态分区.false(不开启) true(开启)默认是 false hive.exec.dynamic.pa ...

  8. python 文件监听

    对文件进行监听.过滤 def tail(filename): f = open(file=filename, mode='r', encoding='utf-8') # 打开文件不能用with,因为监 ...

  9. python 进程信号量

    1.概念 信号量和锁相似,锁同一时间只允许一个对象(进程)通过,信号量同一时间允许多个对象(进程)通过 2.应用场景 多线程,并规定数量 3.格式: 导入信号量模块 实例化信号量对象,可以规定信号量的 ...

  10. 搞定SpringBoot多数据源(3):参数化变更源

    目录 1. 引言 2. 参数化变更源说明 2.1 解决思路 2.2 流程说明 3. 实现参数化变更源 3.1 改造动态数据源 3.1.1 动态数据源添加功能 3.1.2 动态数据源配置 3.2 添加数 ...