最短增广路

请先理解 bfs的求增广路的算法,再来学习Isap算法

最短增广路Isap算法


图片来源 《趣学算法》人民邮电出版社 陈小玉

/*
最短可增广路:重贴标签算法Isap
算法设计:
1、确定合适数据结构,采用邻接表存储网络。
2、对网络结点贴标签,即标高操作。
3、对源点的高度>=结点数,则转向第(6)步,否则从源点开始,沿着高度h(u)=h(v)+1且有可行邻接边(cap>flow)
的方向前进,如果到达汇点,则转向第(4)步;如果无法行进,则转向第(5)步。
4、增流操作:沿着找到的可增广路同向边增流,反向边剑流。注意:在原网络上操作。
5、重贴标签:如果拥有当前结点高度的结点只有一个,则转向第(6)步;令当前结点的高度=所有邻接点高度的最小值+1,如果没有可行邻接边,
则令当前结点的高度=结点数;退回一步;转向第(3)步。
6、算法结束:已找到最大流。
*/
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int INF=0x3fffffff;
const int N=100;//最大结点数
const int M=10000;//最大边数
int top;
int h[N],pre[N],g[N];
//h[]记录各结点的高度
//g[]记录距离h[]的结点的个数,g[3]记录h为3的结点个数        E[i]
//pre[]记录结点的前驱边,根据pre可以倒推可增广路径pre[v]=i ----->v
//邻接表头结点
struct Vertex{int first;//first记录E[M]的M 为N->v的边
}V[N];
struct Edge{int v,next;int cap,flow;
}E[M];
void init(){memset(V,-1,sizeof(V));//初始化V[all].first=-1top=0;//记录E[]使用到了那里了
}
//-->
void add_edge(int u,int v,int c){//添加单条边//参数 u v及u-->v边的容量cE[top].v=v;E[top].cap=c;E[top].flow=0;//头插法E[top].next=V[u].first;V[u].first=top;top++;
}
void add(int u,int v,int c){//添加正负两边add_edge(u,v,c);add_edge(v,u,0);
}
//-->
void set_h(int t,int n){//标高函数,t源点 n汇点queue<int>Q;//广度优先搜索memset(h,-1,sizeof(h));//初始化各结点的高为-1memset(g,0,sizeof(g));//全部高度的结点数量为0h[t]=0;//汇点高度为0Q.push(t);//汇点入队列while(!Q.empty()){int v=Q.front();Q.pop();//对头出队列++g[h[v]];//高度为h[v]的数量+1for(int i=V[v].first;i!=-1;i=E[i].next){//遍历结点v的临界点及v-->someint u=E[i].v;if(h[u]==-1){//还没有标记过h[u]=h[v]+1;Q.push(u);//入队列}}}cout<<"Init hight Value\n";cout<<"h[ ]=";for(int i=1;i<=n;i++){cout<<" "<<h[i];}cout<<endl;
}//参数  s:源点 t:汇点 n:总结点个数
//返回值  网络最大流
int Isap(int s,int t,int n){//isap增广算法//初始化标高set_h(t,n);//从t-->nint ans=0,u=s;//ans最大流量,u当前探索到的结点int d;while(h[s]<n){int i=V[u].first;if(u==s){//当前在源点时d=INF;}//搜索当前结点的邻接边for(;i!=-1;i=E[i].next){int v=E[i].v;//u-->v//判断是否满足探索条件:有可增量 且 h[u]-1=h[v]if(E[i].cap>E[i].flow&&h[u]-1==h[v]){u=v;//满足条件则当前位置移到v           E[i]pre[v]=i;//设置v结点的前驱为i 即记录边u------->v//迭代最小增量d=min(d,E[i].cap-E[i].flow);if(u==t){//探索到了汇点printf("增广路径:%d",t);while(u!=s){int j=pre[u];//即增广路汇点的前驱边E[j]E[j].flow+=d;//E[j]流量增dE[j^1].flow-=d;//j的反向边流量-d/*^1:创建边时是成对创建的0^1=1 1^1=0 2^1=3 3^1=2*/u=E[j^1].v;cout<<"---"<<u;}printf("增流: %d\n",d);ans+=d;d=INF;}break;//找到一条可行邻接边,退出for循环,停止寻找可行邻接边}}if(-1==i){//所有邻接边搜索完毕,无法前行if(--g[h[u]]==0){//该高度结点只有1个,算法结束break;}int hmin=n-1;for(int j=V[u].first;j!=-1;j=E[j].next){//搜索u的邻接边if(E[j].cap>E[j].flow){//有可增量hmin=min(hmin,h[E[j].v]);}}h[u]=hmin+1;printf("重贴标签后的高度\n");printf("h[ ]=");for(int i=1;i<=n;i++){printf(" %d",h[i]);}printf("\n");++g[h[u]];//重新贴标签后该高度的结点数+1if(u!=s){//当前结点不是源点u=E[pre[u]^1].v;//退回一步}}}return ans;
}void printg(int n){//输出邻接表for(int i=1;i<=n;i++){cout<<"v"<<i<<" ["<<V[i].first;for(int j=V[i].first;j!=-1;j=E[j].next){cout<<"]--["<<E[j].v<<" "<<E[j].cap<<" "<<E[j].flow<<" "<<E[j].next;}cout<<"]\n";}
}void printflow(int n){//输出实流边,有流量的边printf("Real Stream Network Value:\n");for(int i=1;i<=n;i++){for(int j=V[i].first;j!=-1;j=E[j].next){if(E[j].flow>0){cout<<"v"<<i<<"--"<<"v"<<E[j].v<<" "<<E[j].flow<<endl;;}}}
}int main(void){int n,m;//记录节点数与边数int u,v,w;//u->v cap=wcin>>n>>m;init();for(int i=1;i<=m;i++){cin>>u>>v>>w;add(u,v,w);//添加两条反向边}printg(n);//输出网络邻接表//Isap算法求网络最大流cout<<"network max stream value is:"<<Isap(1,n,n)<<endl;printg(n);//输出邻接表printflow(n);//输出实流边return 0;
}
/*
test example
6 9
1 3 10
1 2 12
2 4 8
3 5 13
3 2 2
4 6 18
4 3 5
5 6 4
5 4 6out:
v1 [2]--[2 12 0 0]--[3 10 0 -1]
v2 [9]--[3 0 0 4]--[4 8 0 3]--[1 0 0 -1]
v3 [13]--[4 0 0 8]--[2 2 0 6]--[5 13 0 1]--[1 0 0 -1]
v4 [17]--[5 0 0 12]--[3 5 0 10]--[6 18 0 5]--[2 0 0 -1]
v5 [16]--[4 6 0 14]--[6 4 0 7]--[3 0 0 -1]
v6 [15]--[5 0 0 11]--[4 0 0 -1]
Init hight Value
h[ ]= 3 2 2 1 1 0
澧炲箍璺緞:6---4---2---1澧炴祦: 8
閲嶈创鏍囩鍚庣殑楂樺害
h[ ]= 3 4 2 1 1 0
澧炲箍璺緞:6---5---3---1澧炴祦: 4
閲嶈创鏍囩鍚庣殑楂樺害
h[ ]= 3 4 2 1 2 0
閲嶈创鏍囩鍚庣殑楂樺害
h[ ]= 3 4 3 1 2 0
閲嶈创鏍囩鍚庣殑楂樺害
h[ ]= 4 4 3 1 2 0
澧炲箍璺緞:6---4---5---3---1澧炴祦: 6
閲嶈创鏍囩鍚庣殑楂樺害
h[ ]= 5 4 3 1 2 0
network max stream value is:18
v1 [2]--[2 12 8 0]--[3 10 10 -1]
v2 [9]--[3 0 0 4]--[4 8 8 3]--[1 0 -8 -1]
v3 [13]--[4 0 0 8]--[2 2 0 6]--[5 13 10 1]--[1 0 -10 -1]
v4 [17]--[5 0 -6 12]--[3 5 0 10]--[6 18 14 5]--[2 0 -8 -1]
v5 [16]--[4 6 6 14]--[6 4 4 7]--[3 0 -10 -1]
v6 [15]--[5 0 -4 11]--[4 0 -14 -1]
Real Stream Network Value:
v1--v2 8
v1--v3 10
v2--v4 8
v3--v5 10
v4--v6 14
v5--v4 6
v5--v6 4
*/

最短增广路Isap算法 网络流相关推荐

  1. 网络流—Edmonds-Karp 最短增广路算法(最大流)

    网络流----Edmonds-Karp 最短增广路算法 ■求最大流的过程,就是不断找到一条源到汇的路径,然后构建残余网络,再在残余网络上寻找新的路径,使总流量增加,然后形成新的残余网络,再寻找新路径- ...

  2. 网络流之 最短增广路算法模板(SAP)

    数据输入格式:首先输入顶点个数n和弧数m,然后输入每条弧的数据.规定源点为顶点0,汇点为顶点n-1.每条弧的数据格式为:u,v,w,分别表示这条弧的起点,终点,容量.顶点序号从0开始. 代码: 1 # ...

  3. 最大流增广路(KM算法) HDOJ 1853 Cyclic Tour

    题目传送门 1 /* 2 KM: 相比HDOJ_1533,多了重边的处理,还有完美匹配的判定方法 3 */ 4 #include <cstdio> 5 #include <cmath ...

  4. SAP和ISAP(网路最大流的两个增广路算法)

    ISAP是对SAP进行优化后的算法,ISAP时间复杂度为O(V^2E),SAP的时间复杂度为O(VE^2) SAP #include <iostream> #include <alg ...

  5. 网络最大流中一般增广路算法(标号法)

    网络最大流主要有两大类求解方法:增广路算法和预流推进算法 一般增广路算法:主要分为初始流为零流和初始流为非零流的情况!后者在标号的时候注意一条边是正向连接还是反向连接:若是反向的连接,那么在调整的时候 ...

  6. 【网络流】解题报告:luogu P2740 [USACO4.2]草地排水Drainage Ditches(Edmonds-Karp增广路,最大流模板)

    题目链接:草地排水 若一条从源点到汇点的路径上各条边的剩余容量都大于0,则称这条路径为一条增广路. Edmonds-Karp增广路的策略就是不断用bfs寻找增广路,直至网络中不在存在增广路为止. 在每 ...

  7. 增广路算法 (最大流问题)

    Edmonds-Karp算法: 计算机科学中, Edmonds–Karp算法通过实现Ford–Fulkerson算法来计算网络中的最大流,其时间复杂度为O(V E2). 该算法由Yefim (Chai ...

  8. Sweet Snippet 之 最短增广路径算法

    本文简单实现了最短增广路径算法 首先我们简单实现 queue(队列) 数据结构 : local queue = {} queue.__index = queuefunction queue:push( ...

  9. 网络流 增广路 回退

    增广路: 有流量标记: 流量变化: 转载于:https://www.cnblogs.com/cmyg/p/9568904.html

最新文章

  1. C语言中的字符串处理
  2. 陌陌股价过山车背后隐藏了什么?
  3. 获取上传文件的后缀名
  4. Oracle 数据库
  5. noj数据结构稀疏矩阵的加法十字链表_数据结构之:图
  6. 主板24pin接口详图_【图解】主板连线接口最详尽图文解释
  7. robotFramework-ride使用2-分支与循环
  8. 所有受限制的应用程序包_您需要了解的有关Mac的Apple新款M1芯片的所有信息
  9. php并发数据库操作,数据库的并发操作
  10. 粉笔画粉笔字体样式_20多种很棒的粉笔字体可供下载
  11. 王元元主编书籍计算机数学基础,计算机的数学基础有哪些
  12. 国内有哪些不错的CV(计算机视觉)团队?
  13. linux ubantu最新版本,过去十年最佳的Ubuntu版本
  14. EasyUI 中文乱码问题
  15. 分支界限法 任务分配问题
  16. 计算机文化基础第一章知识点题,计算机文化基础第一章习题与答案
  17. 黑客软件大众化 【爆吧机的出现】杨丞琳贴吧遭网友攻陷
  18. 跨境电商「独角兽」融资40亿+,这家公司是怎么做增长的?
  19. C++11 bind函数
  20. 二极管反向恢复时间和反向恢复电流

热门文章

  1. oracle物化视图可以创建索引,oracle 物化视图及创建索引
  2. Comsol学习笔记5:如何发挥计算机的性能,并行计算
  3. NLP——4.朴素贝叶斯
  4. 在Mac下,如何完美的卸载应用程序?-AppCleaner
  5. spring 狂神说的详细笔记(完整版)
  6. [JAVA]如何使用百度 API STORE —— 以翻译接口为例
  7. 使用Arduino开发板连接模拟pH传感器
  8. Android项目——不成熟的计算器
  9. 在线文档协作:办公必备高效率神器
  10. 突破圈层,个体崛起,欢迎想突破自己的你