最大流算法-ISAP
引入
最大流算法分为两类,一种是增广路算法,一种是预留推进算法。增广路算法包括时间复杂度\(O(nm^2)\)的EK算法,上界为\(O(n^2m)\)的Dinic算法,以及一些其他的算法。EK算法直接进行增广,而Dinic则是通过沿着最短路增广优化了复杂度,它的做法是每次进行bfs求出层次图,再dfs沿着层次图进行多路增广。然而,Dinic中每次进行bfs求层次图似乎有点浪费,因为层次图的改动并不是非常大。在这种思路下,我们考虑直接在每次dfs增广的时候修改层次图来优化求最短路的过程。
算法
ISAP (Improved Shortest Augment Path) 算法其实是通过dfs中不断修改距离标号\(d\)的方式省去了每次的bfs,所以称为improved。
Dinic算法中,我们需要每次搜索出层次图,而在ISAP中,我们只需要每次dfs的过程中修改距离标号。具体来说,我们用\(d[x]\)表示残余网络上\(x\)到汇点\(t\)的最短距离,我们每次沿着\(d[x]=d[v]+1\)的路增广。如果点\(x\)的出边的点没有发现满足这个条件的那么就说明当前的最短路已经过时了,我们需要修改距离标号。修改距离标号,就是让\(x\)可以至少有一个点可以增广,所以取所有\(d[v]\)中最小的那个加一即可。这样增广下去,当\(d[s]\),即\(s\)到\(t\)的距离大于等于\(n\)的时候,就说明至少有一个点经过了两次,即不存在增广路了,这个时候算法退出。
复杂度
ISAP的复杂度上界其实就是Dinic复杂度去掉bfs的部分。接下来我们证明Dinic的复杂度,再说明ISAP的复杂度上界。
Dinic算法每次求出层次图,然后dfs多路增广。可以发现,当dfs退出的时候,可以增广的所有路径都已经增广完了。考虑每一次\(t\)的层次标号,可以发现,如果一次dfs完,下一次bfs得到\(t\)的层次标号与上一次一样,那么就是说,上一次还有没有增广完的路径,这显然是不可能的。那么\(t\)的层次标号是否可能减少呢?如果可以的话,那么上一次也可以找到更短的路径,因为残余网络的增广会把边变成反向。这样,每次bfs的时候得到的\(t\)层次编号是严格递增的,也就是说,\(n\)次阶段以内一定可以结束算法。bfs的复杂度为\(O(m)\),dfs的复杂度看似是\(O(m)\)的,其实不然。考虑一个满足\((u,v,w)\),其中\(w\)为\(v\)可以到达的点的数量的网络流原图,那么一次dfs可以达到\(nm\)。这样看来,整个过程分成了\(n\)个阶段,每一阶段为\(O(nm)\),所以总共是\(O(n^2m)\)。
ISAP的复杂度上界与这个是相同的。
优化
接下来我们将看到ISAP是如何被极大地优化的。
- 如果一开始把距离标号都设为0,那么dfs最多需要\(O(n^2)\)来把距离标号初始化,而我们可以最开始逆向bfs一次,\(O(n+m)\)初始化所有距离标号。
- 如果距离标号出现了断层,那么显然不存在新的增广路。我们用一个gap数组记录每种层次标号有多少个,如果当前修改了最后一个某种层次标号,那么就出现了前后断层,结束算法。
- 增广过程中,如果一个点的标号没有修改过,那么它已经遍历过的边不需要再遍历一次,所以我们存下每次遍历到哪条边,下一次从这条边开始遍历(因为有可能到这里之后流量用完了,但是还没有增广完)。
- 最短路的修改具有连续性,即我们不需要每次求后继的标号最小值,而是直接给标号加一。
- 同Dinic中,如果流量用完了直接退出。
ISAP非常好地结合标号的思想优化了SAP算法,编程复杂度极低(我的递归版主过程只有30行),可以作为网络流算法的首选。
UPDATE:谁能告诉我ISAP在什么数据下会被卡掉!!
代码
poj1273网络流模板题。
#include<cstdio>
#include<cctype>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
int read() {
int x=0,f=1;
char c=getchar();
for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
for (;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=205;
const int maxm=205;
const int inf=2e9+7;
struct edge {
int v,w,nxt;
} e[maxm<<1];
int h[maxn],tot,n,m,gap[maxn],last[maxn],d[maxn],que[maxn],ql,qr;
vector<int> inv[maxn];
void add(int u,int v,int w) {
e[++tot]=(edge){v,w,h[u]};
h[u]=tot;
e[++tot]=(edge){u,0,h[v]};
h[v]=tot;
}
void init(int s,int t) {
memset(gap,0,sizeof gap),memset(d,0,sizeof d),++gap[d[t]=1];
for (int i=1;i<=n;++i) last[i]=h[i];
que[ql=qr=1]=t;
while (ql<=qr) {
int x=que[ql++];
for (int i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v) if (!d[v]) ++gap[d[v]=d[x]+1],que[++qr]=v;
}
}
int aug(int x,int s,int t,int mi) {
if (x==t) return mi;
int flow=0;
for (int &i=last[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v) if (d[x]==d[v]+1) {
int tmp=aug(v,s,t,min(mi,e[i].w));
flow+=tmp,mi-=tmp,e[i].w-=tmp,e[i^1].w+=tmp;
if (!mi) return flow;
}
if (!(--gap[d[x]])) d[s]=n+1;
++gap[++d[x]],last[x]=h[x];
return flow;
}
int maxflow(int s,int t) {
init(s,t);
int ret=aug(s,s,t,inf);
while (d[s]<=n) ret+=aug(s,s,t,inf);
return ret;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#endif
while (~scanf("%d%d",&m,&n)) {
tot=1,memset(h,0,sizeof h);
for (int i=1;i<=n;++i) inv[i].clear();
for (int i=1;i<=m;++i) {
int u=read(),v=read(),w=read();
add(u,v,w);
if (w) inv[v].push_back(u);
}
int ans=maxflow(1,n);
printf("%d\n",ans);
}
return 0;
}
最大流算法-ISAP的更多相关文章
- 最大流算法 ISAP 模板 和 Dinic模板
ISAP // UVa11248 Frequency Hopping:使用ISAP算法,加优化 // Rujia Liu struct Edge { int from, to, cap, flow; ...
- Ford-Fulkerson 最大流算法
流网络(Flow Networks)指的是一个有向图 G = (V, E),其中每条边 (u, v) ∈ E 均有一非负容量 c(u, v) ≥ 0.如果 (u, v) ∉ E 则可以规定 c(u, ...
- 算法9-5:最大流算法的Java代码
残留网络 在介绍最大流算法之前先介绍一下什么是残留网络.残余网络的概念有点类似于集合中的补集概念. 下图是残余网络的样例. 上面的网络是原始网络.以下的网络是计算出的残留网络.残留网络的作用就是用来描 ...
- 海量数据挖掘MMDS week3:流算法Stream Algorithms
http://blog.csdn.net/pipisorry/article/details/49183379 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...
- 基于.net的分布式系统限流组件(限流算法:令牌算法和漏斗算法)
转载链接:https://www.cnblogs.com/vveiliang/p/9049393.html 1.令牌桶算法 令牌桶算法是比较常见的限流算法之一,大概描述如下: 1).所有的请求在处理之 ...
- 常用限流算法与Guava RateLimiter源码解析
在分布式系统中,应对高并发访问时,缓存.限流.降级是保护系统正常运行的常用方法.当请求量突发暴涨时,如果不加以限制访问,则可能导致整个系统崩溃,服务不可用.同时有一些业务场景,比如短信验证码,或者其它 ...
- Cable TV Network 顶点连通度 (最大流算法)
Cable TV Network 题目抽象:给出含有n个点顶点的无向图,给出m条边.求定点联通度 K 算法:将每个顶点v拆成 v' v'' ,v'-->v''的容量为1. ...
- 最大流算法之ISAP
序: 在之前的博文中,我解释了关于最大流的EK与Dinic算法,以及它们的STL/非STL的实现(其实没什么区别).本次讲解的是ISAP算法.'I',指 inproved,也就是说ISAP其实是SAP ...
- 最大流算法-最高标号预流推进(HLPP)
昨天我们学习了ISAP算法,它属于增广路算法的大类.今天学习的算法是预流推进算法中很高效的一类--最高标号预流推进(HLPP). 预流推进 预流推进是一种很直观的网络流算法.如果给到一个网络流让你手算 ...
随机推荐
- 20155336 2016-2017-2 《Java程序设计》第四周学习总结
20155336 2016-2017-2 <Java程序设计>第四周学习总结 教材学习内容总结 第六章 继承:面向对象中,为避免多个类间重复定义共同行为.(简单说就是将相同的程序代码提升为 ...
- vagrant boxes
vagrant box add hashicorp/precise64
- 【LG3232】[HNOI2013]游走
题面 洛谷 题解 代码 #include<iostream> #include<cstdio> #include<cstdlib> #include<cstr ...
- Linux系统运维基础管理命令总结
1.查看系统负载命令:w.uptime [root@localhost ~]# w :: up days, :, user, load average: 0.00, 0.01, 0.05 USER T ...
- javaweb(八)——HttpServletResponse对象(二)
一.HttpServletResponse常见应用——生成验证码 1.1.生成随机图片用作验证码 生成图片主要用到了一个BufferedImage类, 生成随机图片范例: 1 package gacl ...
- 现有新的iOS更新可用,请从iOS12 beta版进行更新.解决方案
问题描述: ios系统一直弹出“现有新的iOS更新可用,请从iOS12 beta版进行更新”的提示,很烦的. 应该只出现在安装测试版ios12的手机上. 解决方案: 删除描述文件无法解决. 有网友机制 ...
- 二、Django快速安装
一.安装Python 作为一个Python Web框架,Django依赖Python.从Django适用于哪些版本的Python可以获取更多信息.较新版本的Python内置一个轻量级的数据库SQLit ...
- [二读]The Art of Pompeii's Influence on Neo-Classicism
The Art of Pompeii's Influence on Neo-Classicism The discovery of Pompeii's ruins in 1599 profoundly ...
- Lua学习笔记(4): 字符串
Lua的字符串有3种初始化方式 str = "2333" str = 'hahahaha' str = [[ruarua]] 其中单引号和双引号的初始化方式并无区别,[[]]双中括 ...
- 【ANSIBLE】ansible控制windows插件安装及运行error与解决方法
一. 问:因pip版本问题无法安装kerberos 答:安装提示需要先安装pip升级包 下载pip9.0.1升级包: https://pypi.python.org/packages/b6/ac/70 ...