前置知识

网络最大流入门

前言

Dinic在信息学奥赛中是一种最常用的求网络最大流的算法。

它凭借着思路直观,代码难度小,性能优越等优势,深受广大oier青睐

思想

$Dinic$算法属于增广路算法。

它的核心思想是:对于每一个,对其所连的边进行增广,在增广的时候,每次增广“极大流”

这里有别于EK算法,EK算法是从边入手,而Dinic算法是从点入手

在增广的时候,对于一个点连出去的边都尝试进行增广,即多路增广

Dinic算法还引入了分层图这一概念,即对于$i$号节点,用$dis(i)$表示它到源点的距离,并规定,一条边能够被增广,当且仅当它连接的两个点$u,v$满足:$dis(v)=dis(u)+1$,这样可以大大优化其时间复杂度。

实现

有了上面的知识,Dinic实现起来也就比较简单了。

每次BFS构造分层图(注意必须每次都重新构造,因为每次增广之后会删除一些无用的边,也就会删除一些无用的点)

然后从源点开始多路增广

优化

  • 当前弧优化:对于每个点,我们记录下它已经增广了哪些边,当再次回到这个点的时候,无视已经增广过的边,从下一条边开始增广
  • 分层优化(自己xjb起的名字):在进行分层的时候,找到汇点立即退出
  • 剩余量优化(也是自己起的):在进行增广的时候,如果该节点已经没有流量,直接退出

时间复杂度

Dinic算法的理论时间复杂度为$O(n^2*m)$

证明可以看这里

但是!

Dinic算法的性能在比赛中表现的非常优越。

按照集训队大佬ly的说法,我们可以认为Dinic算法的时间复杂度是线性的(比某标号算法不知道高到哪里去了)

代码

题目链接

#include<cstdio>
#include<cstring>
#include<queue>
#define AddEdge(x,y,z) add_edge(x,y,z),add_edge(y,x,0);
using namespace std;
const int MAXN=1e6+;
const int INF=1e8+;
inline char nc()
{
static char buf[MAXN],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,,MAXN,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
char c=nc();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=nc();}
while(c>=''&&c<=''){x=x*+c-'';c=nc();}
return x*f;
}
int N,M,S,T;
struct node
{
int v,flow,nxt;
}edge[MAXN*];
int head[MAXN],cur[MAXN],num=;//注意这里必须从0开始
inline void add_edge(int x,int y,int z)
{
edge[num].v=y;
edge[num].flow=z;
edge[num].nxt=head[x];
head[x]=num++;
}
int deep[MAXN],q[MAXN];
inline bool BFS()
{
memset(deep,,sizeof(deep));
deep[S]=;
int l=,r=;
q[++l]=S;
while(l<=r)
{
int p=q[l++];
for(int i=head[p];i!=-;i=edge[i].nxt)
if(!deep[edge[i].v]&&edge[i].flow)
{
deep[edge[i].v]=deep[p]+;q[++r]=edge[i].v;
if(edge[i].v==T) return ;//当找到汇点的时候直接返回 快30ms
}
}
return deep[T];
}
int DFS(int now,int nowflow)
{
if(now==T) return nowflow;
int totflow=;//从这个点总共可以增广多少流量
for(int i=head[now];i!=-;i=edge[i].nxt)//当前弧优化 快150ms
{
if(deep[edge[i].v]==deep[now]+&&edge[i].flow)//只有满足距离要求与流量要求的点才能进行增广
{
int canflow=DFS(edge[i].v,min(nowflow,edge[i].flow));
edge[i].flow-=canflow;edge[i^].flow+=canflow;//增广
totflow+=canflow;
nowflow-=canflow;
if(nowflow<=) break; //当前点已经没有流量 快100ms
}
}
return totflow;
}
void Dinic()
{
int ans=;
while(BFS())//每次构造分层图
{
memcpy(cur,head,sizeof(head)); //当前弧优化
ans+=DFS(S,INF);//进行增广
}
printf("%d",ans);
}
int main()
{
#ifdef WIN32
freopen("a.in","r",stdin);
#else
#endif
N=read();M=read();S=read();T=read();
memset(head,-,sizeof(head));
for(int i=;i<=M;i++)
{
int x,y,z;
x=read();y=read();z=read();
AddEdge(x,y,z);
}
Dinic();
return ;
}

网络最大流算法—Dinic算法及优化的更多相关文章

  1. POJ 1459 Power Network(网络最大流,dinic算法模板题)

    题意:给出n,np,nc,m,n为节点数,np为发电站数,nc为用电厂数,m为边的个数.      接下来给出m个数据(u,v)z,表示w(u,v)允许传输的最大电力为z:np个数据(u)z,表示发电 ...

  2. 网络流入门—用于最大流的Dinic算法

    "网络流博大精深"-sideman语 一个基本的网络流问题 最早知道网络流的内容便是最大流问题,最大流问题很好理解: 解释一定要通俗! 如右图所示,有一个管道系统,节点{1,2,3 ...

  3. 浅谈最大流的Dinic算法

    PART 1 什么是网络流 网络流(network-flows)是一种类比水流的解决问题方法,与线性规划密切相关.网络流的理论和应用在不断发展,出现了具有增益的流.多终端流.多商品流以及网络流的分解与 ...

  4. 【最大流之Dinic算法】POJ1273 【 & 当前弧优化 & 】

    总评一句:Dinic算法的基本思想比较好理解,就是它的当前弧优化的思想,网上的资料也不多,所以对于当前弧的优化,我还是费了很大的功夫的,现在也一知半解,索性就写一篇博客,来发现自己哪里的算法思想还没理 ...

  5. 最大流EK算法/DINIC算法学习

    之前一直觉得很难,没学过网络流,毕竟是基础知识现在重新来看. 定义一下网络流问题,就是在一幅有向图中,每条边有两个属性,一个是cap表示容量,一个是flow 表示流过的流量.我们要求解的问题就是从S点 ...

  6. [学习笔记] 网络最大流的HLPP算法

    #define \(u\)的伴点集合 与\(u\)相隔一条边的且\(u\)能达到的点的集合 \(0x00~ {}~Preface\) \(HLPP(Highest~Label~Preflow~Push ...

  7. 【网络流相关】最大流的Dinic算法实现

    Luogu P3376 于\(EK\)算法求最大流时每一次只求一条增广路,时间复杂度会比较高.尽管实际应用中表现比较优秀,但是有一些题目还是无法通过. 那么我们就会使用\(Dinic\)算法实现多路增 ...

  8. 一般增广路方法求网络最大流(Ford-Fulkerson算法)

    /* Time:2015-6-18 接触网络流好几天了 写的第一个模版————Ford-Fulkerson算法 作用:求解网络最大流 注意:源点是0 汇点是1 如果题目输入的是1到n 请预处理减1 * ...

  9. HDU1532最大流 Edmonds-Karp,Dinic算法 模板

    Drainage Ditches Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...

随机推荐

  1. 【转载】AngularJS 用$sce服务来过滤HTML标签,解决无法正确显示后台传递的html标签

    angular js的强大之处之一就是他的数据双向绑定这一牛B功能,我们会常常用到的两个东西就是ng-bind和针对form的ng-model.但在我们的项目当中会遇到这样的情况,后台返回的数据中带有 ...

  2. UVa 11025 The broken pedometer【枚举子集】

    题意:给出一个矩阵,这个矩阵由n个数的二进制表示,p表示用p位二进制来表示的一个数 问最少用多少列就能将这n个数区分开 枚举子集,然后统计每一种子集用了多少列,维护一个最小值 b[i]==1代表的是选 ...

  3. caffe命令及其参数解析

    caffe的c++主程序(caffe.cpp)放在根目录下的tools文件夹内, 当然还有一些其它的功能文件,如:convert_imageset.cpp, train_net.cpp, test_n ...

  4. 最新linux运维高级架构课13期 架构师课程

    有会员购买的,分享给大家.完整一套,可以学习一下.     ├─L001-2017linux运维高级架构师13期-运维与自动化运维发展-10节 │      1-1运维职业发展.avi │      ...

  5. 外媒分析:iPhone销量低于预期是中国市场疲软影响的

    根据外媒AppleInsider的报道,来自摩根士丹利(Morgan Stanley)的Katy Huberty是最新一位下调苹果目标股价的分析师,她在报告中写道,iPhone的销量低于预期,主要是因 ...

  6. Android 查看CPU及内存

    借助getprop.dumpsys来了解一些系统相关信息. 一.getprop adb shell cat /system/build.prop 文件中存放的是用于启动系统时需要的配置文件,通常可以通 ...

  7. Git 服务器更换了IP的解决方法

    1.找到项目根目录中的.git文件夹 2..git文件夹里有一个config文件 3.用记事本打开后,修改为服务器的新ip就行了.

  8. ArcGIS api for javascript——查询,然后单击显示信息窗口

    描述 本例展示如何配置查询任务为示例的工作流程: 1.用户单击一个要素来加亮显示. 2.用户再一次单击要素来查看属性信息的 InfoWindow. 本例查询USA州,因此ESRI_StateCityH ...

  9. TI C66x DSP 四种内存保护问题 -之- 外设訪问corePac内部资源时的内存保护问题

    外设訪问corePac内部资源(L1,L2)时的内存保护等问题请參考以下两个blog.已经叙述的非常具体. "TI C66x DSP 系统events及其应用 - 2"," ...

  10. [Python] ndArray of numpy

    NumPy Reference: Mathematical functions numpy.sum: Sum of elements - along rows, columns or all nump ...