以前在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. 1041 考试座位号 (15 分)C语言

    每个 PAT 考生在参加考试时都会被分配两个座位号,一个是试机座位,一个是考试座位.正常情况下,考生在入场时先得到试机座位号码,入座进入试机状态后,系统会显示该考生的考试座位号码,考试时考生需要换到考 ...

  2. FIND_IN_SET 精确查找

    FIND_IN_SET(str,strlist) mysql专为精确匹配字符串而设置的函数 一个字符串列表就是一个由一些被‘,’符号分开的自链组成的字符串 1,2,3,4,5,6,7,8,9: 此函数 ...

  3. Java 集合的工具类Collections的常用方法

    Collections类 java.utils.Collections是集合工具类,用来对集合进行操作. Collections类的常用方法 这里介绍四个常用方法: addAll(Collection ...

  4. python对象的初始化

    效果图: 代码: # 对象的初始化 class Person: # 在类中可以定义一些特殊方法(魔术方法) # 特殊方法都是以__开头,__结尾的方法 前后都是两个下划线 # 特殊方法会在特殊的时刻自 ...

  5. vue学习--组件之间的传值方式

    1.概述 vue由多个组件构成页面,在不同的组件中有不同的联系,组件之间的传值是十分有必要的 2.父子组件之间传值 --props和$emit 父传子:通过props 方法:子组件:props:['m ...

  6. cogs 14. [网络流24题] 搭配飞行员 二分图最大匹配 匈牙利算法

    14. [网络流24题] 搭配飞行员 ★★   输入文件:flyer.in   输出文件:flyer.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述]     飞行大队有 ...

  7. DP-Fibonacci

    善于发现 DP 中的 Fibonacci 我们在做 DP  题时  , 会发现有一些题 类似于找规律的题 ,观察测试样例 , 要对数据敏感 , 比如输入 2 输出 1 , 输入 3 就输出 2 …… ...

  8. 字典树(增删改查 HDU 5687)

    度熊手上有一本神奇的字典,你可以在它里面做如下三个操作: 1.insert : 往神奇字典中插入一个单词 2.delete: 在神奇字典中删除所有前缀等于给定字符串的单词 3.search: 查询是否 ...

  9. 架构师JavaScript 的对象继承方式,有几种程序写法?

    架构师JavaScript 的对象继承方式,有几种程序写法?   一.对象冒充 其原理如下:构造函数使用 this 关键字给所有属性和方法赋值(即采用类声明的构造函数方式).因为构造函数只是一个函数, ...

  10. 团队项目—Beta版本冲刺(2/3)

    团队信息 何全江(队长) 201731024218 胡志伟 201731024240 李元港 201731024232 孟诚成 201731024242 罗俊杰 201731024226 雷安勇 20 ...