POJ1273 网络流-->最大流-->模板级别-->最大流常用算法总结
一般预流推进算法:
算法思想:
对容量网络G 的一个预流f,如果存在活跃顶点,则说明该预流不是可行流。
预流推进算法就是要选择活跃顶点,并通过它把一定的流量推进到它的邻接顶点,尽可能将正的赢余减少为0。
由于算法最终目的是尽可能将流量推进到汇点Vt,因此算法总是首先寻求将流量推进到距离汇点Vt 最近的邻接顶点中。
由于每个顶点的距离标号可以表示顶点到汇点Vt 的距离,因此算法总是将流量沿着允许弧推进。
如果从当前活跃顶点出发没有允许弧,则增加该顶点的距离标号,使得从当前活跃顶点出发至少有一条允许弧。
算法实现基本框架:
(1) (预处理)取零流作为初始可行流,即f = { 0 },对源点Vs 发出的每条<Vs, u>,令f(Vs, u)= c(Vs, u);对任意的顶点v∈V,计算精确的距离标号d(v);令d(Vs) = n;
(2) 如果残留网络G'(V', E')中不存在活跃顶点,则算法结束,已经求得最大流,否则进入第(3)步;
(3) 在残留网络中选取活跃顶点u;如果存在顶点u 的某条出弧<u, v>为允许弧,则将min{ e(u),c'(u, v) }流量的流从顶点u 推进到顶点v;
否则令d(u) = min{ d(v)+1 | <u, v>∈E',且c'(u, v)>0}。转第(2)步。c'(u, v)为残留网络中弧<u, v>的容量。
名词解释:
赢余(excess):设u 是容量网络G(V, E)中的顶点,定义顶点u 的赢余为流入顶点u 的流量之和减去从顶点u 流出的流量之和,记为e(u)。
活跃顶点(active vertex):容量网络G 中,e(u) > 0 的顶点u(u≠Vs、Vt)称为活跃顶点。
预流(preflow):设f = { f(u, v) }是容量网络G(V, E)上的一个网络流,如果G 的每一条弧<u, v>都满足:0 ≤ f(u, v) ≤ c(u, v),<u, v>∈E。
另外,除源点Vs、汇点Vt 外每个顶点u的赢余e(u)都满足:e(u) ≥ 0,u≠Vs、Vt,则称该网络流f 为G 的预流。
算法实现:
- #include <bits/stdc++.h>//poj不支持超级头文件
- using namespace std;
- #define INF 0x3f3f3f3f
- const int maxn = 222;
- struct Push_Relablel//封装一般预流推进算法的结构体,时间复杂度O(n*n*m);
- {
- int res[maxn][maxn];//残留网络
- int dist[maxn];//距离函数
- int e[maxn];//赢余
- int n;//结点数
- int max_flow;//最大流
- void init(int x)
- {
- n = x;
- memset(res, 0, sizeof(res));
- memset(dist, 0, sizeof(dist));
- memset(e, 0, sizeof(e));
- }
- void add(int u, int v, int c)
- {
- res[u][v] += c;
- }
- int push_relablel(int s, int t)
- {
- max_flow = 0;
- queue<int> Q;
- Q.push(s);
- e[s] = INF; e[t] = INF;
- dist[s] = n;
- while(!Q.empty())
- {
- int u = Q.front(); Q.pop();
- for(int i = 1; i <= n; ++i)
- {
- int p = res[u][i] < e[u] ? res[u][i] : e[u];
- if(p>0 && (u == s || dist[u] == dist[i] + 1))
- {
- res[u][i] -=p;
- res[i][u] +=p;
- if(i == t) max_flow += p;
- e[u] -= p;
- e[i] += p;
- if(i!=s && i!=t) Q.push(i);
- }
- }
- if(u!=s && u!=t && e[u] > 0)
- {
- dist[u]++;
- Q.push(u);
- }
- }
- return max_flow;
- }
- } G;
- int main()
- {
- int m, n, u, v, c;
- while(~scanf("%d%d", &m, &n))
- {
- G.init(n);
- while(m--)
- {
- scanf("%d%d%d", &u, &v, &c);
- G.add(u, v, c);
- }
- cout<<G.push_relablel(1, n)<<endl;
- }
- return 0;
- }
最高标号预流推进算法:
算法思想:
一般预流推进算法的缺陷在于非饱和推进。
从具有最大距离标号的活跃节点开始预流推进,使得距离标号较小的活跃顶点累积尽可能多的来自距离标号较大的活跃顶点的流量,然后对累积的盈余进行推进,可能会减少非饱和推进的次数。
用优先队列优化即可。
算法实现:
- #include <bits/stdc++.h>
- using namespace std;
- #define INF 0x3f3f3f3f
- const int maxn = 222;
- struct List
- {
- int x, dist;
- List(int x_, int dist_): x(x_), dist(dist_){}
- bool friend operator < (const List& a, const List& b){
- return a.dist < b.dist;
- }
- };
- struct Push_Relablel //最高标号预流推进算法,时间复杂度O(n * n * sqrt(m))
- {
- int res[maxn][maxn];
- int dist[maxn];
- int e[maxn];
- int n;
- int max_flow;
- void init(int x)
- {
- n = x;
- memset(res, 0, sizeof(res));
- memset(dist, 0, sizeof(dist));
- memset(e, 0, sizeof(e));
- }
- void add(int u, int v, int c)
- {
- res[u][v] += c;
- }
- int push_relablel(int s, int t)
- {
- max_flow = 0;
- dist[s] = n;
- e[s] = INF; e[t] = INF;
- priority_queue<List> Q;
- Q.push(List(s, dist[s]));
- while(!Q.empty())
- {
- List q = Q.top(); Q.pop();
- int u = q.x;
- for(int i = 1; i <= n; ++i)
- {
- int p = res[u][i] < e[u] ? res[u][i] : e[u];
- if(p>0 && (u==s || dist[u] == dist[i] + 1))
- {
- res[u][i] -= p; res[i][u] += p;
- if(i == t) max_flow += p;
- e[u] -= p; e[i] += p;
- if(i != s && i != t) Q.push(List(i, dist[i]));
- }
- }
- if(u!=s && u!=t && e[u]>0)
- {
- dist[u]++;
- Q.push(List(u, dist[u]));
- }
- }
- return max_flow;
- }
- } G;
- int main()
- {
- int m, n, u, v, c;
- while(~scanf("%d%d", &m, &n))
- {
- G.init(n);
- while(m--)
- {
- scanf("%d%d%d", &u, &v, &c);
- G.add(u, v, c);
- }
- cout<<G.push_relablel(1, n)<<endl;
- }
- return 0;
- }
最短增广路算法(SAP):
算法思想:
每次在层次网络中找一个含弧最少的增广路进行增广;
算法实现步骤:
(1) 初始化容量网络和网络流;
(2) 构造残留网络和层次网络,若汇点不在层次网络中,则算法结束;
(3) 在层次网络中不断用BFS 增广,直到层次网络中没有增广路为止;每次增广完毕,在层次网络中要去掉因改进流量而导致饱和的弧;
(4) 转步骤(2)。
算法实现:
- #include <cstdio>
- #include <cstring>
- #include <queue>
- #include <iostream>
- using namespace std;
- #define INF 0x3f3f3f3f
- const int maxn = 222;
- struct EK //Edmonds-Krap 算法,又称SAP算法,时间复杂度O(n*m*m);
- {
- int res[maxn][maxn];
- int pre[maxn];
- int n;
- void init(int x)
- {
- n = x;
- memset(res, 0, sizeof(res));
- }
- void add(int u, int v, int c)
- {
- res[u][v] += c;
- }
- bool bfs(int s, int t)
- {
- queue<int> Q;
- memset(pre, -1, sizeof(pre));
- Q.push(s);
- while(!Q.empty())
- {
- int u = Q.front(); Q.pop();
- for(int i = 1; i <= n; ++i)
- {
- if(res[u][i] && pre[i] == -1) //有增广量而没有加入增广路
- {
- pre[i] = u;
- if(i == t) return true;
- Q.push(i);
- }
- }
- }
- return false;
- }
- int sap(int s, int t)
- {
- int max_flow = 0;
- while(bfs(s, t))
- {
- int a = INF;
- for(int i = t; i != s; i = pre[i])
- a = min(a, res[pre[i]][i]);
- for(int i = t; i != s; i = pre[i])
- {
- res[pre[i]][i] -= a;
- res[i][pre[i]] += a;
- }
- max_flow += a;
- }
- return max_flow;
- }
- } G;
- int main()
- {
- int n, m, u, v, c;
- while(~scanf("%d%d", &m, &n))
- {
- G.init(n);
- while(m--)
- {
- scanf("%d%d%d", &u, &v, &c);
- G.add(u, v, c);
- }
- cout<< G.sap(1, n) <<endl;
- }
- return 0;
- }
连续最短增广路算法(Dinic):
算法思想:
Dinic 算法的思想也是分阶段地在层次网络中增广。它与最短增广路算法不同之处是:在Dinic 算法中,只需一次DFS 过程就可以实现多次增广。
算法实现步骤:
(1) 初始化容量网络和网络流;
(2) 构造残留网络和层次网络,若汇点不在层次网络中,则算法结束;
(3) 在层次网络中用一次DFS 过程进行增广,DFS 执行完毕,该阶段的增广也执行完毕;
(4) 转步骤(2)。
算法实现:
- #include <bits/stdc++.h>
- using namespace std;
- #define INF 0x3f3f3f3f
- const int maxn = 222;
- struct Dinic //时间复杂度O(n*n*m)
- {
- int res[maxn][maxn];
- int dist[maxn];
- int n;
- void init(int x)
- {
- n = x;
- memset(res, 0, sizeof(res));
- }
- void add(int u, int v, int c)
- {
- res[u][v] += c;
- }
- int bfs(int s)
- {
- memset(dist, 0xff, sizeof(dist));
- dist[s] = 0;
- queue<int> Q;
- Q.push(s);
- while(!Q.empty())
- {
- int u = Q.front(); Q.pop();
- for(int i = 1; i <= n; ++i)
- {
- if(dist[i] < 0 && res[u][i] > 0)
- {
- dist[i] = dist[u] + 1;
- Q.push(i);
- }
- }
- }
- if(dist[n] > 0) return true;
- return false;
- }
- int Find(int x, int low)
- {
- int a = 0;
- if(x == n) return low;
- for(int i = 1; i <= n; ++i)
- {
- if(res[x][i] > 0 && dist[i] == dist[x] + 1 && (a = Find(i, min(low, res[x][i]))))
- {
- res[x][i] -= a;
- res[i][x] += a;
- return a;
- }
- }
- return 0;
- }
- int dinic(int s, int t)
- {
- int max_flow = 0, tmp;
- while(bfs(1))
- {
- while(tmp = Find(1, INF))
- max_flow += tmp;
- }
- return max_flow;
- }
- } G;
- int main()
- {
- int m, n, u, v, c;
- while(~scanf("%d%d", &m, &n))
- {
- G.init(n);
- while(m--)
- {
- scanf("%d%d%d", &u, &v, &c);
- G.add(u, v, c);
- }
- cout<< G.dinic(1, n) <<endl;
- }
- return 0;
- }
POJ1273 网络流-->最大流-->模板级别-->最大流常用算法总结的更多相关文章
- [转载 ]POJ 1273 最大流模板
转载 百度文库花了5分下的 不过确实是自己需要的东西经典的最大流题POJ1273 ——其他练习题 POJ3436 . 题意描述: 现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条水渠,给 ...
- HDU2686 费用流 模板
Matrix Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- 【Luogu】P3376网络最大流模板(Dinic)
最大流模板成为另一个被攻克的模板题. 今天QDC给我讲了一下Dinic,感觉很好懂.于是为了巩固就把这道题A掉了. 核心思想就是不断BFS分层,然后不断DFS找增广路.找不到之后就可以把答案累加输出了 ...
- hdu1533 费用流模板
Going Home Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total ...
- 最大流 && 最小费用最大流模板
模板从 这里 搬运,链接博客还有很多网络流题集题解参考. 最大流模板 ( 可处理重边 ) ; const int INF = 0x3f3f3f3f; struct Edge { int from ...
- 图论算法-最小费用最大流模板【EK;Dinic】
图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...
- ZOJ_2314_Reactor Cooling_有上下界可行流模板
ZOJ_2314_Reactor Cooling_有上下界可行流模板 The terrorist group leaded by a well known international terroris ...
- Drainage Ditches---hdu1532(最大流, 模板)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1532 最大流模板题: EK:(复杂度为n*m*m); #include<stdio.h> ...
- HDU3376 最小费用最大流 模板2
Matrix Again Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Others)To ...
随机推荐
- PHP二分查找算法
思路:递归算法.在一个已经排好序的数组中查找某一个数值,每一次都先跟数组的中间元素进行比较,若相等则返回中间元素的位置,若小于中间元素,则在数组中小于中间元素的部分查找,若大于中间元素,则在数组中大于 ...
- LeetCode 289. Game of Life (生命游戏)
According to the Wikipedia's article: "The Game of Life, also known simply as Life, is a cellul ...
- 【20171025早】alert(1) to win 练习
本人黑绝楼,自称老黑,男,25岁,曾经在BAT工作过两年,但是一直都是底层人员,整天做重复性工作,甚敢无趣,曾和工作十年之久的同事聊天,发现对方回首过往,生活是寡淡如水,只有机械性工作.旋即老黑毅然决 ...
- java springmvc+bui+bootstrap后台管理系统搭建
先来说说bui,这个框架是阿里巴巴的一个前端团队研发的,能够用很少的代码快速搭建一个后台管理系统,很适做管理平台的开发, 之前用过类似这样的框架extjs,做个比较,这个框架实现功能比extjs的代码 ...
- 使用 LitJson 解析Json并读取数据
开发中经常要获取各种数据,而现今比较常见的数据便是Json数据格式,网上也有很多解析Json数据的方法,但是 作为小白的我,对于那些个高大上的方法理解不够,这不找了许久发了这些一个 LitJson 库 ...
- Spring框架学习之高级依赖关系配置(一)
上篇文章我们对Spring做了初步的学习,了解了基本的依赖注入思想.学会简单的配置bean.能够使用Spring容器管理我们的bean实例等.但这还只是相对较浅显的内容,本篇将介绍bean的相关更高级 ...
- Problem Q
Problem Description A factory produces products packed in square packets of the same height h and of ...
- HDU 4267 A Simple Problem with Integers(树状数组区间更新)
A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others) Memory Limit: 32768/32768 K ...
- java中的缓冲流BufferedWriter和BufferedReader
java中的缓冲流有BufferedWriter和BufferedReader 在java api 手册中这样说缓冲流: 从字符输入流中读取文本,缓冲各个字符,从而实现字符.数组和行的高效读取.可以指 ...
- GoldenGate 传统抽取进程随 DataGuard 主备快速切换的方案(ADG 模式)
环境描述: 1.节点描述 节点 IP 节点描述 11.6.76.221 GG 抽取端 / DG 节点,数据库版本号为 Oracle-11.2.0.3,与 11.6.76.222 组成 DataGuar ...