网络流 ISAP算法
2016-02-02 22:20
579 查看
网络流问题:
我自己理解,在流网络中,在不违背容量限制的条件下,解决各种从源点到汇点的问题。
ISAP算法概念:
据说不会有卡ISAP时间的题目………时间复杂度O(E^2*V)
首先原理都是基于不断寻找增广路,属于增广路方法。普通的SAP算法比如EK算法,Dinic 算法,由于在寻找增广路时,都需要先进行BFS,BFS时间复杂度O(E),所以总的时间复杂度最坏情况达到O(VE2)。
ISAP算法的优化在于距离标号,即每个顶点到达终点 t 的距离。所以可以在遍历的过程中,就建立了一个分层网络,不需要每一次都对全图进行BFS遍历,提高了效率。
算法实现过程:
1.反向 BFS 初始化所有顶点的距离标号。(由于在在循环中自动建立起分层网络,所以不需要进行也可以,据大神博客,有无相差5%的时间左右)。
2.当前顶点 V为终点时增广。
3. 当前顶点有满足 dist[V] = dist[j] + 1 的出弧时前进。
4. 当前顶点无满足条件的出弧时重标号并回退一步。整个循环当源点 s 的距离标号 dist[s] >= n 时结束。对V点的重标号操作为 dist[i] = 1 + min。min为对于V相邻的dis最小(离汇点最近)的点。
先对几个概念的理解:
1.增广路:假设我们已经找到了一条从源点到汇点的路径,如果这条路上得每一段路径的此时的流量都小于容量,那么可以确定一个最小的差delta,那么每一段加上delta,就可以得到一个更大的流,即增广路。
2.距离标号:就是某个点到汇点的最少的弧的数量(即边权值为1时某个点到汇点的最短路径长度)。设点i的标号为level[i],那么如果将满足level[i]=level[j]+1的弧(i,j)叫做允许弧 ,且增广时只走允许弧。
3.反向边:简单的说反向边的作用就是给程序一个可以后悔的机会。直接说原因,寻找最优增广路(最大流)其实是有一定的顺序,但是程序不可能预知,所以在每一次对于流量的操作,都 在反方向增加一个回溯流量。
即 map[pre[i]][i]-=aug;
map[i][pre[i]]+=aug;
4.断层(GAP优化思想):gap[i]数组表示距离标号为i的点有多少个,如果到某一点没有符合距离标号的允许弧,那么需要修改距离标号来找到增广路。如果重标号使得gap数组中原标号数目变为0,即修改则无法到达,则算法结束。
代码:
具体还是一遍遍看代码理解….
例题:hdu 1532http://acm.hdu.edu.cn/showproblem.php?pid=1532
邻接矩阵版:
我自己理解,在流网络中,在不违背容量限制的条件下,解决各种从源点到汇点的问题。
ISAP算法概念:
据说不会有卡ISAP时间的题目………时间复杂度O(E^2*V)
首先原理都是基于不断寻找增广路,属于增广路方法。普通的SAP算法比如EK算法,Dinic 算法,由于在寻找增广路时,都需要先进行BFS,BFS时间复杂度O(E),所以总的时间复杂度最坏情况达到O(VE2)。
ISAP算法的优化在于距离标号,即每个顶点到达终点 t 的距离。所以可以在遍历的过程中,就建立了一个分层网络,不需要每一次都对全图进行BFS遍历,提高了效率。
算法实现过程:
1.反向 BFS 初始化所有顶点的距离标号。(由于在在循环中自动建立起分层网络,所以不需要进行也可以,据大神博客,有无相差5%的时间左右)。
2.当前顶点 V为终点时增广。
3. 当前顶点有满足 dist[V] = dist[j] + 1 的出弧时前进。
4. 当前顶点无满足条件的出弧时重标号并回退一步。整个循环当源点 s 的距离标号 dist[s] >= n 时结束。对V点的重标号操作为 dist[i] = 1 + min。min为对于V相邻的dis最小(离汇点最近)的点。
先对几个概念的理解:
1.增广路:假设我们已经找到了一条从源点到汇点的路径,如果这条路上得每一段路径的此时的流量都小于容量,那么可以确定一个最小的差delta,那么每一段加上delta,就可以得到一个更大的流,即增广路。
2.距离标号:就是某个点到汇点的最少的弧的数量(即边权值为1时某个点到汇点的最短路径长度)。设点i的标号为level[i],那么如果将满足level[i]=level[j]+1的弧(i,j)叫做允许弧 ,且增广时只走允许弧。
3.反向边:简单的说反向边的作用就是给程序一个可以后悔的机会。直接说原因,寻找最优增广路(最大流)其实是有一定的顺序,但是程序不可能预知,所以在每一次对于流量的操作,都 在反方向增加一个回溯流量。
即 map[pre[i]][i]-=aug;
map[i][pre[i]]+=aug;
4.断层(GAP优化思想):gap[i]数组表示距离标号为i的点有多少个,如果到某一点没有符合距离标号的允许弧,那么需要修改距离标号来找到增广路。如果重标号使得gap数组中原标号数目变为0,即修改则无法到达,则算法结束。
代码:
具体还是一遍遍看代码理解….
例题:hdu 1532http://acm.hdu.edu.cn/showproblem.php?pid=1532
邻接矩阵版:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; #define MAXN 222 #define inf 100000000+1000 int map[MAXN][MAXN];//存图 int pre[MAXN];//记录当前点的前驱 int level[MAXN];//记录距离标号 int gap[MAXN];//gap常数优化 int NV,NE; //可以加入一个反向的BFS,优化些许时间。 //入口参数vs源点,vt汇点 int SAP(int vs,int vt){ memset(pre,-1,sizeof(pre)); memset(level,0,sizeof(level)); memset(gap,0,sizeof(gap)); gap[0]=vt; int v,u=pre[vs]=vs,maxflow=0,aug=inf; while(level[vs]<vt) { //寻找可行弧 for(v=1;v<=vt;v++){ if(map[u][v]>0&&level[u]==level[v]+1){ break; } } if(v<=vt){ pre[v]=u; u=v; if(v==vt){ aug=inf; //寻找当前找到的一条路径上的最大流 for(int i=v;i!=vs;i=pre[i]){ if(aug>map[pre[i]][i])aug=map[pre[i]][i]; } maxflow+=aug; //更新残留网络 for(int i=v;i!=vs;i=pre[i]){ map[pre[i]][i]-=aug; map[i][pre[i]]+=aug; } u=vs;//从源点开始继续搜 } } else { //找不到可行弧 int minlevel=vt; //寻找与当前点相连接的点中最小的距离标号 for(v=1;v<=vt;v++){ if(map[u][v]>0&&minlevel>level[v]){ //离vt最近的点 minlevel=level[v]; } } gap[level[u]]--;//(更新gap数组)当前标号的数目减1; if(gap[level[u]]==0) break;//出现断层 如果出现断层,则该点为一个唯一点,后退也没有意义 level[u]=minlevel+1; gap[level[u]]++; u=pre[u]; //相当于后退一步 } } return maxflow; } int main(){ int n,m,u,v,cap; while(~scanf("%d%d",&m,&n)){ memset(map,0,sizeof(map)); for(int i=1;i<=m;i++){ scanf("%d%d%d",&u,&v,&cap); map[u][v]+=cap; } printf("%d\n",SAP(1,n)); } return 0; }
相关文章推荐
- 计算机网络4--Internet结构
- linux网络编程2
- 网络游戏到底该服务大众玩家还是大R?
- http://www.osyunwei.com/archives/4788.html
- 胡伯涛论文阅读手记
- Android网络开发之用tcpdump抓包
- vm11下安装ubuntu14.04出现的网络问题解决方案
- Ksoap2和HttpTransportSE的一点使用
- ActiveMQ之 TCP通讯机制
- HTTPClient模块的HttpGet和HttpPost
- Android 网络请求Volley库完全解析,Volley的基本用法(一)
- HTTP接口例子
- IIS中如何应用程序启用https协议
- 神经网络
- iOS9----HTTPS 进行网络请求的解决方案
- Androidx学习笔记(41)---使用异步HttpClient(android-async-http-master)做Post提交
- HTTP访问控制(CORS)
- Androidx学习笔记(40)--- 使用异步HttpClient(android-async-http-master)做get提交
- Androidx学习笔记(39)--- 使用HttpClient框架做POST提交
- IPv6下网络编程实例