SAP和ISAP(网路最大流的两个增广路算法)
ISAP是对SAP进行优化后的算法,ISAP时间复杂度为O(V^2E),SAP的时间复杂度为O(VE^2)
SAP
- #include <iostream>
- #include <algorithm>
- #include <iomanip>
- #include <queue>
- using namespace std;
- const int maxn = 100;
- const int INF = (1 << 30) - 1;
- int g[maxn][maxn];//残余网络
- int f[maxn][maxn];//实流网络
- int Prev[maxn];//保存前驱节点
- bool visited[maxn];
- int n, m;
- bool BFS(int s,int t)
- {
- int i;
- memset(Prev, -1, sizeof(Prev));
- memset(visited, false, sizeof(visited));//初始化
- queue<int> q;
- visited[s] = true;
- q.push(s);
- while (!q.empty())
- {
- int now = q.front();
- q.pop();
- for (i = 1; i <= n; i++)
- {
- if (!visited[i] && g[now][i]>0)//没被访问并且有边相连
- {
- visited[i] = true;
- Prev[i] = now;
- if (i == t)return true;//找到一条增广路劲
- q.push(i);
- }
- }
- }
- return false;
- }
- int EK(int s, int t)
- {
- int v, w, d, maxflow;
- maxflow = 0;
- while (BFS(s, t))//还有增广路径
- {
- v = t;
- d = INF;
- while (v != s)//向前找
- {
- w = Prev[v];
- if (d > g[w][v])
- {
- d = g[w][v];
- }
- v = w;
- }
- maxflow += d;
- v = t;
- while (v != s)
- {
- w = Prev[v];
- g[w][v] -= d;
- g[v][w] += d;
- if (f[v][w] > 0)
- {
- f[v][w] -= d;
- }
- else
- f[w][v] += d;
- v = w;
- }
- }
- return maxflow;
- }
- void Print()
- {
- cout << endl;
- for (int i = 1; i <= n; i++)
- {
- cout << setw(7) << "v" << i;
- }
- cout << endl;
- for (int i = 1; i <= n; i++)
- {
- cout<< "v" << i;
- for (int j = 1; j <= n; j++)
- {
- cout << setw(7) << f[i][j] << " ";
- }
- cout << endl;
- }
- }
- int main()
- {
- int u, v, w;
- memset(g, 0, sizeof(g));
- memset(f, 0, sizeof(f));
- cin >> n >> m;
- for (int i = 1; i <= m; i++)
- {
- cin >> u >> v >> w;
- g[u][v] += w;
- }
- cout << EK(1, n) << endl;
- Print();
- return 0;
- }
ISAP
- #include <iostream>
- #include <algorithm>
- #include <queue>
- using namespace std;
- const int INF = 0x3fffffff;
- const int M = 10000;
- const int N = 100;
- int g[N], h[N], parent[N];//g[n]表示高度为h[n]的节点的个数h[n]节点高度数组
- int top;
- struct Vexter
- {
- int first;
- }V[N];
- struct Edge//边结构体
- {
- int v, next;
- int flow, cap;
- }E[N];
- void init()
- {
- memset(V, -1, sizeof(V));
- top = 0;
- }
- void add_Edge(int u, int v, int c)
- {
- E[top].cap = c;
- E[top].flow = 0;
- E[top].next = V[u].first;
- E[top].v = v;
- V[u].first = 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)
- {
- queue<int> q;
- memset(g, 0, sizeof(g));
- memset(h, -1, sizeof(h));
- h[t] = 0;
- q.push(t);//汇点进队
- while (!q.empty())
- {
- int v = q.front();
- q.pop();
- ++g[h[v]];
- for (int i = V[v].first; ~i; i = E[i].next)
- {
- int u = E[i].v;
- if (h[u] == -1)
- {
- h[u] = h[v] + 1;
- q.push(u);
- }
- }
- }
- cout << "初始化高度" << endl;
- cout << "h[ ]=";
- for (int i = 1; i <= n; i++)
- {
- cout << " " << h[i];
- }
- cout << endl;
- }
- int Isap(int s, int t, int n)
- {
- set_h(t, n);//标高
- int ans = 0, u = s, d;
- while (h[s] < n)
- {
- int i = V[u].first;
- if (u == s)
- {
- d = INF;
- }
- for (; ~i; i = E[i].next)
- {
- int v = E[i].v;
- if (E[i].cap>E[i].flow&&h[u] == h[v] + 1)
- {
- u = v;
- parent[v] = i;
- d = min(d, E[i].cap - E[i].flow);
- if (u == t)//到达汇点
- {
- cout << endl;
- cout << "增广路径: " << t;
- while (u != s)//向前到源点
- {
- int j = parent[u];
- E[j].flow += d;//反向边增流
- E[j ^ 1].flow -= d;
- u = E[j ^ 1].v;
- cout << "--" << u;
- }
- cout << "增流: " << d << endl;
- ans += d;
- d = INF;
- }
- break;
- }
- }
- if (i == -1)//搜索所有边后不能进行
- {
- if (--g[h[u]] == 0)
- {
- break;
- }
- int hmin = n - 1;
- for (int j = V[u].first; ~j; j = E[j].next)
- {
- if (E[j].cap > E[j].flow)
- {
- hmin = min(hmin, h[E[j].v]);
- }
- }
- h[u] = hmin + 1;
- cout << "重贴标签后的高度:" << endl;
- cout << "h[ ]=";
- for (int i = 1; i <= n; i++)
- {
- cout << " " << h[i];
- }
- cout << endl;
- ++g[h[u]];
- if (u != s)//回退一步
- {
- u = E[parent[u] ^ 1].v;
- }
- }
- }
- return ans;
- }
- void PrintFlow(int n)
- {
- cout << "-----实流边-----" << endl;
- for (int i = 1; i <= n; i++)
- {
- for (int j = V[i].first; ~j; j = E[j].next)
- {
- if (E[j].flow > 0)
- {
- cout << "v" << i << "--" << "v" << E[j].v << " " << E[j].flow;
- cout << endl;
- }
- }
- }
- }
- int main()
- {
- int n, m, u, v, c;
- cin >> n >> m;
- init();
- for (int i = 1; i <= m; i++)
- {
- cin >> u >> v >> c;
- add(u, v, c);
- }
- cout << endl;
- cout << "网络的最大流: " << Isap(1, n, n) << endl;
- PrintFlow(n);
- return 0;
- }
SAP和ISAP(网路最大流的两个增广路算法)相关推荐
- 网络最大流中一般增广路算法(标号法)
网络最大流主要有两大类求解方法:增广路算法和预流推进算法 一般增广路算法:主要分为初始流为零流和初始流为非零流的情况!后者在标号的时候注意一条边是正向连接还是反向连接:若是反向的连接,那么在调整的时候 ...
- 网络流—Edmonds-Karp 最短增广路算法(最大流)
网络流----Edmonds-Karp 最短增广路算法 ■求最大流的过程,就是不断找到一条源到汇的路径,然后构建残余网络,再在残余网络上寻找新的路径,使总流量增加,然后形成新的残余网络,再寻找新路径- ...
- 网络流之 最短增广路算法模板(SAP)
数据输入格式:首先输入顶点个数n和弧数m,然后输入每条弧的数据.规定源点为顶点0,汇点为顶点n-1.每条弧的数据格式为:u,v,w,分别表示这条弧的起点,终点,容量.顶点序号从0开始. 代码: 1 # ...
- 最短增广路Isap算法 网络流
最短增广路 请先理解 bfs的求增广路的算法,再来学习Isap算法 最短增广路Isap算法 图片来源 <趣学算法>人民邮电出版社 陈小玉 /* 最短可增广路:重贴标签算法Isap 算法设计 ...
- 【网络流】解题报告:luogu P2740 [USACO4.2]草地排水Drainage Ditches(Edmonds-Karp增广路,最大流模板)
题目链接:草地排水 若一条从源点到汇点的路径上各条边的剩余容量都大于0,则称这条路径为一条增广路. Edmonds-Karp增广路的策略就是不断用bfs寻找增广路,直至网络中不在存在增广路为止. 在每 ...
- 最大流增广路(KM算法) HDOJ 1853 Cyclic Tour
题目传送门 1 /* 2 KM: 相比HDOJ_1533,多了重边的处理,还有完美匹配的判定方法 3 */ 4 #include <cstdio> 5 #include <cmath ...
- 网络流:最大流,最小割 基本概念及算法
原文:http://www.cnblogs.com/Booble/archive/2011/03/04/1970453.html 参考:http://community.topcoder.com/tc ...
- 最大流的算法——Edmonds-Karp算法(最短路径增广算法)
最大流的算法--Edmonds-Karp算法(最短路径增广算法) 这里介绍一个最简单的算法:Edmonds-Karp算法 即最短路径增广算法 简称EK算法 EK算法基于一个基本的方法:Ford-Ful ...
- 算法学习笔记:网络流#4——ISAP 求解最大流
算法学习笔记:网络流#4--ISAP 求解最大流 1. 前言 2. 模板 2.1 详解 2.2 正确性证明 2.3 代码 3. 算法对比 3.1 一般数据下的对比 3.2 特殊数据下的对比 4. 总结 ...
最新文章
- 转: 浅析Fusion-IO和Intel SSD
- 《HTML5触摸界面设计与开发》——导读
- python 消息机制_Python并发编程之线程消息通信机制任务协调(四)
- 状态模式 设计模式_设计模式:状态
- 《零基础》MySQL 管理(三)
- 作者:陈钧,男,中国国防科技信息中心高级工程师、研究室主任。
- cmd查看开放的端口
- (转)华为面试题算什么,这个背会了外企随便进
- 从零基础入门Tensorflow2.0 ----三、10. 近似求导
- java开发利器 eclipse从入门到精通 pdf_Java从入门到精通(第4版)高清PDF下载
- Linux驱动开发-编写OLED显示屏驱动
- 【单片机仿真】(二)keil 安装教程
- vmware使用显卡
- NDoc 用户指南(转)
- 极米H5值得入手吗?极米H5实际体验如何?画面对比实测
- 董卫凤:不服输的华丽转身(三)
- 国外7个免费的网络主机服务
- Apache http Server与Tomcat整合 2
- 云服务器+ngrok搭建内网穿透服务(只有公网ip无域名)
- LCD显示器的模拟和数字接口