网络流——基础,Dinic和Sap(Gap优化)算法
网络流的三个基本性质:
1、容量限制: f[u,v]<=c[u,v]2、反对称性:f[u,v] = - f[v,u]3、流量平衡: 对于不是源点也不是汇点的任意结点,流入该结点的流量和等于流出该结点的流量和。
增广路算法:
每次暴力找一条由源点到汇点的增广路,算入答案,记得连反向弧。
时间复杂度:O(n6n^6)
听说有一种算法叫两百行的高标推进,非常快——
Dinic:
每次给算出源点到各个点的最短距离,然后我们按照最短路径找增广路,直到源点不能找到汇点;
cur当前弧优化:
如果这条弧已经流完,那么我们下次没有必要再经过它,于是在链式前向星里标记就好了。
二分图时间复杂度:O(nm−−√n \sqrt{m})
Code:
#include <cstdio>
#include <cstring>
#include <algorithm>using namespace std;const int maxn = 100005,maxm = 100005;struct node
{int to,next,flow;//目标点,下一条边,剩余流量node(void){}node(int a,int b,int c) : to(a),next(b),flow(c){}
}e[maxm * 2];//正向+反向弧int d[maxn];//距离标号,距离原点的最短距离
int final[maxn],cur[maxn];
int n,m,tot,s,t;void link(int u,int v,int c)
{e[++ tot] = node(v,final[u],c),final[u] = tot;e[++ tot] = node(u,final[v],0),final[v] = tot;
// 2 3 //这里保证了正,反向弧的标号连续,那么对于第i条边,其反向弧就是i^1
}bool bfs()
{//用bfs找到每个点的距离标号static int que[maxn];for(int i = s;i <= t;i ++) d[i] = -1,cur[i] = final[i];d[s] = 0;que[1] = s;for(int fi = 1,en = 1;fi <= en;fi ++){int u = que[fi];for(int i = final[u];i;i = e[i].next)if (e[i].flow > 0 && d[e[i].to] == -1){d[e[i].to] = d[u] + 1;que[++ en] = e[i].to;}}return d[t] != -1;
}int dfs(int now,int flow)
{if (now == t) return flow;//流完,退出int use = 0;for(int i = cur[now];i;i = e[i].next){cur[now] = i;if (e[i].flow > 0 && d[e[i].to] == d[now] + 1/*只能沿着最短路走*/){int tmp = dfs(e[i].to,min(e[i].flow,flow - use));use += tmp,e[i].flow -= tmp,e[i ^ 1].flow += tmp;if (flow == use) return use;}}return use;
}int main()
{tot = 1;//计算反向弧时更方便scanf("%d%d", &n, &m);//n为点数,m为边数s = 1,t = n;//假定原点为s,汇点为tfor(int i = 1;i <= m;i ++){int u,v,c;scanf("%d%d%d", &u, &v, &c);//一条从u到v,流量为c的边link(u,v,c);}int ans = 0;for(;bfs()/*假如找不到证明无法增广*/;)ans += dfs(s,1 << 30);printf("%d\n", ans);return 0;
}
Sap:
Dinic每次需要宽搜,最多n次,影响了时间。
sap的思想是分层图的思想,这一层我们流完了,那么我们就绕远路去另外一层。
记录dxd_x表示x的层数,我们本来只去x+1这一层,现在x+1层流完了,就去x+2层。
gap优化:
用co统计每一层的个数,如果出现了断层,就说明源点不能再流到汇点了,直接退出。
为了代码实现方便,通常使co0co_0=0,而不是宽搜弄初始层数。
Code:
#include <cstdio>
#include <cstring>
#include <algorithm>using namespace std;const int maxn = 100005,maxm = 100005;struct node
{int to,next,flow;//目标点,下一条边,剩余流量node(void){}node(int a,int b,int c) : to(a),next(b),flow(c){}
}e[maxm * 2];//正向+反向弧int d[maxn];//距离标号,距离汇点的最短距离
int co[maxn];//co[i] = |{k|d[k]=i}|,gap优化
int final[maxn],cur[maxn];
int n,m,tot,s,t;void link(int u,int v,int c)
{e[++ tot] = node(v,final[u],c),final[u] = tot;e[++ tot] = node(u,final[v],0),final[v] = tot;//这里保证了正,反向弧的标号连续,那么对于第i条边,其反向弧就是i^1
}int dfs(int now,int flow)
{if (now == t) return flow;//流完,退出int use = 0;for(int i = cur[now];i;i = e[i].next){cur[now] = i;//当前弧优化if (e[i].flow > 0 && d[e[i].to] + 1 == d[now]/*只能沿着最短路走*/){int tmp = dfs(e[i].to,min(e[i].flow,flow - use));use += tmp,e[i].flow -= tmp,e[i ^ 1].flow += tmp;if (flow == use) return use;}}cur[now] = final[now];if (!(-- co[d[now]])) d[s] = n;//gap++ co[++ d[now]];return use;
}int main()
{tot = 1;//计算反向弧时更方便scanf("%d%d", &n, &m);//n为点数,m为边数s = 1,t = n;//假定原点为s,汇点为tfor(int i = 1;i <= m;i ++){int u,v,c;scanf("%d%d%d", &u, &v, &c);//一条从u到v,流量为c的边link(u,v,c);}co[0] = n;//初始化,每个点的d都为0int ans = 0;for(;d[s] < n;) ans += dfs(s,1 << 30/*一个较大的值*/);printf("%d\n", ans);return 0;
}
总结
在赛场时,因为网络流复杂度玄学,通常把两种算法都打了,比较一下在这种图下是Dinic快还是Sap快,再提交。
网络流真正的难点永远是建图,所以算法实现倒不显得那么重要,可是也必须熟练掌握,清楚每个步骤的原理。
网络流——基础,Dinic和Sap(Gap优化)算法相关推荐
- 【机器学习基础】各种梯度下降优化算法回顾和总结
论文标题:An overview of gradient descent optimization algorithms 原文链接:https://arxiv.org/pdf/1609.04747.p ...
- 非均匀变异的互利自适应缎蓝园丁鸟优化算法-附代码
非均匀变异的互利自适应缎蓝园丁鸟优化算法 文章目录 非均匀变异的互利自适应缎蓝园丁鸟优化算法 1.缎蓝园丁鸟优化算法 2.非均匀变异的互利自适应缎蓝园 2.1 非均匀变异 2.2 互利因子 2.3自适 ...
- 基于自适应权重的缎蓝园丁鸟优化算法-附代码
基于自适应权重的缎蓝园丁鸟优化算法 文章目录 基于自适应权重的缎蓝园丁鸟优化算法 1.缎蓝园丁鸟优化算法 2.改进的缎蓝园丁鸟优化算法 2.1 自适应权重 2.2 改进原高斯变异形式 3.实验结果 5 ...
- 数学建模——多目标规划模型(智能优化算法NSGA-II)
摘要 本篇笔记对数学建模中常见的多目标规划问题提供了解法:在建立传统的多目标规划的常用模型的基础上,使用智能优化算法对多目标规划问题进行求解,通过Pareto Front直观展现非劣解的分布情况,以解 ...
- BZOJ3698 XWW的难题(上下界网络流+gap优化的细节处理)
XWW给你一个N*N的正实数矩阵A,满足XWW性. 称一个N*N的矩阵满足XWW性当且仅当:(1)A[N][N]=0:(2)矩阵中每行的最后一个元素等于该行前N-1个数的和:(3)矩阵中每列的最后一个 ...
- 深度学习基础(基本概念、优化算法、初始化、正则化等)
2020-04-25 16:29:09 引言 深度学习目前已成为发展最快.最令人兴奋的机器学习领域之一,许多卓有建树的论文已经发表,而且已有很多高质量的开源深度学习框架可供使用.然而,论文通常非常简明 ...
- Java的知识点18——数组存储表格数据、冒泡排序的基础算法、冒泡排序的优化算法、二分法查找
数组存储表格数据 package cn.dym08; import java.util.Arrays; public class Test09 {public static void main(Str ...
- 【机器学习基础】优化算法详解
本文来源于吴恩达老师的深度学习课程[1]和深度学习课程[2]笔记部分. 作者:黄海广[3] 备注:笔记和作业(含数据.原始作业文件).视频都在 github[4]中下载. 导语 在学习机器学习的过程中 ...
- 08 线性回归 + 基础优化算法【动手学深度学习v2】
线性回归 输出层不当成一层 输入层和权重层放一起 x和y是列向量 因为loss=1/2(y-y_hat)^2 又因为y_hat的平均值=1/n(xi*w+b)=1/n(Xw+b) 唯一一个有显示解的模 ...
- 商品pid是什么意思_0基础搞懂自动驾驶传统算法与深度学习的鸿沟-PID控制算法与MLP优化方法...
0基础搞懂自动驾驶传统算法与深度学习的鸿沟这个专题核心是要思考如何让rule-base的自动驾驶算法逐步提升为data-driven的算法,从而尽可能的提升软件的泛化性.数据驱动的逻辑代替控制,规划, ...
最新文章
- 程序运行慢?你怕是写的假 Python
- 人工智能也能写出如此诗句
- python知识点:上下文管理器[__enter__ 和 __exit__ ]
- 小月金嗓再现经典版迟来的爱
- python 创建目录_Python虚拟环境的搭建与使用
- SE43自定义sap菜单
- 简述:B2B、B2C、C2C、O2O
- Linux闲时自动抢占GPU脚本
- 基于Google Reader发展起来的个性化推荐系统之三大问题
- Netty4.x中文教程系列(二) Hello World !
- 专题导读:面向大数据处理的数据流计算技术
- java 面试题解惑一 类的初始化顺序
- 设计模式(3)——装饰者模式(Decorator,结构型)
- android:Read-only file system解决
- Lua 如何快速的读取一个文件
- PCB Layout 中的直角走线、差分走线和蛇形线
- Python安装和几种Python编程工具介绍
- 洛谷分支结构题单前一半 深基例2到例9 P5710 数的性质 P5711 闰年判断 P5712 Apples P5713 洛谷团队系统 P5714 肥胖问题 P5715 三位数排序 P5716月份天数
- 获奖!CACTER邮件安全网关荣获电子邮件安全优秀产品奖项
- 捷多邦6层板阻抗及压合设计