吐槽

这个算法。。

怎么说........

学来也就是装装13吧。。。。

长得比EK丑

跑的比EK慢

写着比EK难

思想

大家先来猜一下这个算法的思想吧:joy:

看看人家的名字——最高标号预留推进

多么高端大气上档次2333333咳咳

从它的名字中我们可以看出,它的核心思想是—推进,而不是找增广路

那么它是怎么实现推进的呢?

很简单,我们从源点开始,不停的向其他的点加流量,对于每个点都如此操作。那么推到最后,我们就可以得到到达汇点的最大流量

不过可能会出现一种情况,就是$A$送流量给$B$,$B$觉得不好意思不想要,于是又推给$A$,$A$非常热情便又推给$B$……直到推到TLE为止。。那怎么解决这种情况呢?

我们对每个点,引入一个高度$H$,并且规定,一个点$u$可以向另一个点$v$送流量,当且仅当$H[u]=H[s]+1$

这样我们就可以保证不会有上面情况发生了

另外还有一种情况,就是这个点依然有流量,但是迫于高度的限制流不出去,那怎么办呢?

很简单,我们增加这个点的高度,这样这个点的流量就能流出去了。

优化

预留推进也就是这些内容了

但是它的名字里的最高标号是啥意思呢?

这个要感谢咱们的熟人tarjan,他和他的小伙伴发现,如果每次选的点是高度最高的点,时间复杂度会更优。

可以优化至$O(n^2\sqrt{m})$

另外还有一个比较显然的优化,如果一个高度$i$是不存在的,即图中没有高度为$i$的点,那么从比$i$高的点一定不会走到汇点$T$,因为根据我们的限制条件,必须要经过高度为$i$的点,于是这些点就没有用了

代码

题目在这儿

不是我说,这个算法真的是死慢死慢的,,,,

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
const int MAXN=*1e3+;
const int INF=1e8+;
inline char nc()
{
static char buf[MAXN],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,MAXN,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
char c=nc();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=nc();}
while(c>=''&&c<=''){x=x*+c-'';c=nc();}
return x*f;
}
int N,M,S,T;
int H[MAXN];//每个节点的高度
int F[MAXN];//每个节点可以流出的流量
int gap[MAXN];//每个高度的数量
struct node
{
int u,v,flow,nxt;
}edge[MAXN];
int head[MAXN];
int num=;//注意这里num必须从0开始
inline void add_edge(int x,int y,int z)
{
edge[num].u=x;
edge[num].v=y;
edge[num].flow=z;
edge[num].nxt=head[x];
head[x]=num++;
}
inline void AddEdge(int x,int y,int z)
{
add_edge(x,y,z);
add_edge(y,x,);//注意这里别忘了加反向边
}
struct comp
{
int pos,h;
comp(int pos=,int h=):pos(pos),h(h) {}
inline bool operator < (const comp &a) const {return h<a.h;}
};
priority_queue<comp>q;
bool Work(int u,int v,int id)
{
int val=min(F[u],edge[id].flow);
edge[id].flow-=val;edge[id^].flow+=val;
F[u]-=val;F[v]+=val;
return val;
}
inline int HLPP()
{
H[S]=N;F[S]=INF;q.push(comp(S,H[S]));
while(q.size()!=)
{
int p=q.top().pos;q.pop();
if(!F[p]) continue;
for(int i=head[p];i!=-;i=edge[i].nxt)
if( (p==S||H[edge[i].v]+==H[p]) && Work(p,edge[i].v,i) && edge[i].v!=S && edge[i].v!=T)
q.push( comp(edge[i].v,H[edge[i].v]) );
if(p!=S && p!=T && F[p])
{
if( (--gap[ H[p] ])== )//该高度不存在
{
for(int i=;i<=N;i++)
if( H[p]<H[i]&&H[i]<=N && p!=S && p!=T )
H[i]=N+;//设置为不可访问
}
++gap[ ++H[p] ];//高度+1
q.push( comp(p,H[p]) );
}
}
return F[T];
}
int main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
#else
#endif
memset(head,-,sizeof(head));
N=read(),M=read(),S=read(),T=read();
for(int i=;i<=M;i++)
{
int x=read(),y=read(),z=read();
AddEdge(x,y,z);
}
printf("%d", HLPP() );
return ;
}

网络最大流算法—最高标号预流推进HLPP的更多相关文章

  1. 最大流算法-最高标号预流推进(HLPP)

    昨天我们学习了ISAP算法,它属于增广路算法的大类.今天学习的算法是预流推进算法中很高效的一类--最高标号预流推进(HLPP). 预流推进 预流推进是一种很直观的网络流算法.如果给到一个网络流让你手算 ...

  2. ZOJ-2364 Data Transmission 分层图阻塞流 Dinic+贪心预流

    题意:给定一个分层图,即只能够在相邻层次之间流动,给定了各个顶点的层次.要求输出一个阻塞流. 分析:该题直接Dinic求最大流TLE了,网上说采用Isap也TLE,而最大流中的最高标号预流推进(HLP ...

  3. 最大流算法-ISAP

    引入 最大流算法分为两类,一种是增广路算法,一种是预留推进算法.增广路算法包括时间复杂度\(O(nm^2)\)的EK算法,上界为\(O(n^2m)\)的Dinic算法,以及一些其他的算法.EK算法直接 ...

  4. 常用限流算法与Guava RateLimiter源码解析

    在分布式系统中,应对高并发访问时,缓存.限流.降级是保护系统正常运行的常用方法.当请求量突发暴涨时,如果不加以限制访问,则可能导致整个系统崩溃,服务不可用.同时有一些业务场景,比如短信验证码,或者其它 ...

  5. Ford-Fulkerson 最大流算法

    流网络(Flow Networks)指的是一个有向图 G = (V, E),其中每条边 (u, v) ∈ E 均有一非负容量 c(u, v) ≥ 0.如果 (u, v) ∉ E 则可以规定 c(u, ...

  6. 算法9-5:最大流算法的Java代码

    残留网络 在介绍最大流算法之前先介绍一下什么是残留网络.残余网络的概念有点类似于集合中的补集概念. 下图是残余网络的样例. 上面的网络是原始网络.以下的网络是计算出的残留网络.残留网络的作用就是用来描 ...

  7. 最大流算法之ISAP

    序: 在之前的博文中,我解释了关于最大流的EK与Dinic算法,以及它们的STL/非STL的实现(其实没什么区别).本次讲解的是ISAP算法.'I',指 inproved,也就是说ISAP其实是SAP ...

  8. 最大流算法之Ford-Fulkerson算法与Edmonds–Karp算法

    引子 曾经很多次看过最大流的模板,基础概念什么的也看了很多遍.也曾经用过强者同学的板子,然而却一直不会网络流.虽然曾经尝试过写,然而即使最简单的一种算法也没有写成功过,然后对着强者大神的代码一点一点的 ...

  9. coding++:RateLimiter 限流算法之漏桶算法、令牌桶算法--简介

    RateLimiter是Guava的concurrent包下的一个用于限制访问频率的类 <dependency> <groupId>com.google.guava</g ...

随机推荐

  1. truffle 开发入门教程

    1.安装nodejs 2.安装truffle:执行命令: npm install -g truffle 3.truffle init  (可加项目名) 4.windows 要删除根目录中的 truff ...

  2. Spring源码工程导入Eclsipse缺少两个jar文件

    按照<Spring源码深度解析>所述,使用gradle cleanidea eclipse将Spring源码转为eclipse工程后,导入eclipse,最后发现还是缺少spring-cg ...

  3. Redis基础入门,Redis的优点也特点,Redis五种数据类型

    Redis是一个开源,高级的键值存储和一个适用的解决方案,用于构建高性能,可扩展的Web应用程序. 1.Redis的主要特点 Redis有三个主要特点,使它优越于其它键值数据存储系统 - Redis将 ...

  4. SDL 开发实战(一):SDL介绍及开发环境配置

    一.什么是SDL? SDL是 “Simple DirectMedia Layer”的缩写,SDL是一个开源的跨平台的多媒体库,封装了复杂的音视频底层操作,简化了音视频处理的难度. SDL使用C语言写成 ...

  5. [Swift]LeetCode819. 最常见的单词 | Most Common Word

    Given a paragraph and a list of banned words, return the most frequent word that is not in the list ...

  6. zuul进阶学习(二)

    1. zuul进阶学习(二) 1.1. zuul对接apollo 1.1.1. Netflix Archaius 1.1.2. 定期拉 1.2. zuul生产管理实践 1.2.1. zuul网关参考部 ...

  7. windows下golang实现Kfaka消息发送及kafka环境搭建

    kafka环境搭建: 一.安装配置java-jdk (1)kafka需要java环境,安装java-jdk,下载地址:https://www.oracle.com/technetwork/java/j ...

  8. java多线程(3)---synchronized、Lock

    synchronized.Lock 一.概述 1.出现线程不安全的原因是什么? 如果我们创建的多个线程,存在着共享数据,那么就有可能出现线程的安全问题:当其中一个线程操作共享数据时,还未操作完成,另外 ...

  9. qcharts编译

    编译环境vs2013+qt5.5.1+perl5 qchart源码在git上自己下载,或者在此下载,参考文档:Qt Charts 5.7.0 安装教程,这篇文章是使用mingw的方式编译qcharts ...

  10. .NET Core中的路由约束

    背景介绍 上周给大家分享了Nancy in .NET Core学习笔记 - 路由之后, 就一直在考虑.NET Core能否实现和Nancy中一样的路由约束, 最近查阅了一下MSDN及一些国外博客, 发 ...