题目链接(一道模板的最大流问题)


我们都知道,Dinic算法求最大流的时候,每次都是需要去重新跑一遍分层图,那么现在有没有什么不需要再这样一次又一次地跑一遍分层图的做法呢?

我们知道,其实每次改变的深度是不多的,所以由这里去进行优化,于是有了ISAP这个只需要跑一次分层图的算法。

时间复杂度上界是,但是随机数据的时候就跑的飞快了!也就是上界比较的松了。

Improved Shortest Augmeng Path 简称ISAP算法,改善最少增加的路径。

ISAP的做法是,我们利用BFS求出分层图(仅需要一次),dfs来实现多路增广,dfs退出的时候,说明了目前可以增广的路径已经增广完了。因为残余网络的增广会使得原先的边变成反向,这样就会使得每次bfs的时候得到的点的编号都会是递增的(保证了单调性)。也就是说,我们经过N次这样的操作,一定是可以结束算法的。

这样,如果目前情况已经没法继续增广了,我们可以试着去调整它们的高度来进行继续增广。

最开始,我们逆向BFS一次。

初始化,给所有点的距离标号都赋值为0,然后从T开始,deep[T] = 1,从它开始(不考虑流的权值的)往回跑到起点S,并且更新deep,由于是bfs跑的,所以保证了最开始的deep是最小的。

这里加入一个gap优化,gap[]数组记录每一层有多少个点,如果说出现了断层,那么显然是不存在新的增广路了。此时结束算法。

if(!(--gap[deep[u]])) deep[S] = N + 1;
while(deep[S] <= N) ret += aug(S, S, T, INF);

也就是说,当deep[S] > N的时候我们会结束算法。

在增广的过程中,如果一个点的标号没有被修改过,那么它已经遍历过的边不需要再遍历一次,所以我们存下每次遍历到的哪条边,下一次从这条边开始遍历。因为有可能到这里之后流量用完了,但是后面还没有增广完。

for(int i=head[u], v; ~i; i=edge[i].nex)
{v = edge[i].to;if(deep[u] == deep[v] + 1){int tmp = aug(v, S, T, min(FLOW, edge[i].flow));flow += tmp; FLOW -= tmp; edge[i].flow -= tmp; edge[i ^ 1].flow += tmp;if(!FLOW) return flow;}
}

并且,最短路的修改具有连续性,前面也说到了一开始得到的deep一定是最小的(每个点都是),并且一定是线性增加的,那么,我们不需要每次再去跑一遍分层图了,而是可以直接给标号加一。

++gap[++deep[u]];
cur[u] = head[u];

当流量用完之后就可以退出算法了。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 205;
int N, M, head[maxN], cnt;
struct Eddge
{int nex, to, flow;Eddge(int a=-1, int b=0, int c=0):nex(a), to(b), flow(c) {};
}edge[maxN << 1];
inline void addEddge(int u, int v, int w)
{edge[cnt] = Eddge(head[u], v, w);head[u] = cnt++;
}
inline void _add(int u, int v, int w) { addEddge(u, v, w); addEddge(v, u, 0); }
struct ISAP_MaxFlow
{int gap[maxN], cur[maxN], deep[maxN], que[maxN], ql, qr;inline void clear(int S, int T){for(int i=1; i<=N; i++){gap[i] = deep[i] = 0;}++gap[deep[T] = 1];for(int i=1; i<=N; i++) cur[i] = head[i];que[ql = qr = 1] = T;while(ql <= qr){int u = que[ql++];for(int i=head[u], v; ~i; i=edge[i].nex){v = edge[i].to;if(!deep[v]){++gap[deep[v] = deep[u] + 1];que[++qr] = v;}}}}inline int aug(int u, int S, int T, int FLOW){if(u == T) return FLOW;int flow = 0;for(int i=head[u], v; ~i; i=edge[i].nex){v = edge[i].to;if(deep[u] == deep[v] + 1){int tmp = aug(v, S, T, min(FLOW, edge[i].flow));flow += tmp; FLOW -= tmp; edge[i].flow -= tmp; edge[i ^ 1].flow += tmp;if(!FLOW) return flow;}}if(!(--gap[deep[u]])) deep[S] = N + 1;++gap[++deep[u]]; cur[u] = head[u];return flow;}inline int Max_Flow(int S, int T){clear(S, T);int ret = aug(S, S, T, INF);while(deep[S] <= N) ret += aug(S, S, T, INF);return ret;}
} isap;
inline void init()
{cnt = 0;for(int i=1; i<=N; i++) head[i] = -1;
}
int main()
{while(scanf("%d%d", &M, &N) != EOF){init();for(int i=1, u, v, w; i<=M; i++){scanf("%d%d%d", &u, &v, &w);_add(u, v, w);}printf("%d\n", isap.Max_Flow(1, N));}return 0;
}

Drainage Ditches【究极最大流算法之ISAP】(Improved Shortest Augmeng Path)相关推荐

  1. 究极最大流算法(ISAP)(HLPP)

    有2个ISAP(Improved Shortest Augumenting Path),和最高标号预流推进(HLPP). Dinic 和 ISAP 都是O(n2m)O(n^2m)O(n2m),实际表现 ...

  2. 从Dinic到ISAP,从余流推进到最高标号的预留推进HLPP(究极最大流算法)

    题目链接--很好的一道对于网络流提升的题 Dinic 首先,这道题真的将Dinic算法卡到了它的上界,也就是,在这道题中,使用一般的Dinic最后会获得40分. #include <iostre ...

  3. 最大流算法之ISAP

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

  4. 网络流最大流算法(ISAP算法及DINIC算法)

    这些算法网络中解释都有,所有以下是根据题目应用,代码中有注释,方便理解,ISAP算法就是通过先bfs一遍建立逆序求层数,然后每次都进行维护求最短路来求增广路径,下次查找建立在上次查找的最小路径的源点进 ...

  5. 最大流算法-ISAP

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

  6. 最大流算法之三:ISAP

    最大流算法之三:ISAP <转> (2009-08-14 19:24:27) 转载▼ 标签: it 分类: 理论 通常的 SAP 类算法在寻找增广路时总要先进行 BFS,BFS 的最坏情况 ...

  7. USACO Section 4.2 Drainage Ditches(最大流)

    最大流问题.ISAP算法.注意可能会有重边,不过我用的数据结构支持重边.距离d我直接初始化为0,也可以用BFS逆向找一次. -------------------------------------- ...

  8. yolo系列算法思想流程简单讲解概述————(究极简单的讲述和理解)

           在我想学习算法的时候,我看某些大佬特别喜欢上来就讲论文,给我搞的贼难受,毕竟本人太辣鸡了,上来这么搞看不懂,经过诸多算法的这样折磨.我打算根据自己的亲身经历和学习过程中遇到的问题出一期, ...

  9. 网络流--最大流--POJ 1273 Drainage Ditches

    链接 Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clov ...

最新文章

  1. 潜艇将来会无人驾驶吗?
  2. 129. 火车进栈【栈】
  3. English debate for sports motion with notes from PM (feedback included)
  4. Spring @Configuration 和 @Bean 注解
  5. 安装VS 2008 EXPRESS出现无法读取deffactory.dat错误
  6. vue动态切换css文件_vue实现样式之间的切换及vue动态样式的实现方法
  7. windows下dos窗口实现持续ping显示时间保存至日志
  8. 太极计算机ehr系统,(数据科学学习手札21)sklearn.datasets常用功能详解
  9. Struts2 POI 导入导出Excel数据
  10. 电脑下边的任务栏不见了_Win7系统电脑任务栏经常自动消失不见的解决方法
  11. VTK:图像平滑——高斯滤波器
  12. dell 恢复介质_安装DELL原装windows系统,使用 USB 恢复介质来安装 Microsoft Windows
  13. 小学教师计算机国培培训总结,小学教师国培计划研修总结
  14. eclipse使用技巧——备注格式的定义与模板
  15. 计算机前置usb应用,usb前面不能用,详细教您解决电脑前置USB接口不能使用
  16. UE4 Pak相关:加载Pak内模型Mesh/SkMesh没有材质
  17. 年龄识别之ssrnet
  18. 保险丝的常用规格型号及主要参数说明
  19. linux装回win10系统无法开机,Win10/Linux双系统删除之后出现grub无法开机修复方法...
  20. Oracle创建同义词并授权

热门文章

  1. SIP与RTP综合应用(转)
  2. Android ViewDragHelper类
  3. 2014年BN Nook HD/HD+ CM11新手入门+刷机教程,编译自xda,仅供参考
  4. Aplayer音乐播放插件
  5. BWK210-180-05电压输出单轴倾角传感器的使用
  6. 【LINUX修行之路】——工具篇gcc/g++的使用和自动化构建工具make/makefile
  7. 原创超简单代码(1.25)
  8. LoRaWAN 协议规范
  9. 朴素贝叶斯+语言模型
  10. C语言:实验5-1 使用函数计算两个复数之积.2021-07-23