前置知识

网络最大流入门

前言

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. Adobe 2015 CC update (Windows/Mac OS) 独立升级包下载 Adobe Photoshop CC (Windows 32bit)

    Adobe CC 2015 Product Updates/Downloads for Windows ** = To access these updates, please first follo ...

  2. Android框架-Volley(三)

    经过前面两篇文章的学习,我们已经掌握了Volley各种Request的使用方法,包括StringRequest.JsonRequest.ImageRequest等.其中StringRequest用于请 ...

  3. 当fastJson邂逅大写字段时

    在项目中遇到了一件令人头疼的事.使用fastJson反序列化时下面的Json时,得到对象属性总为null(如下图),可能细心的朋友一看就知道问题出在哪里,没错!问题就出在返回的字段首字母给大写了.fa ...

  4. NodeJS学习笔记 进阶 (9)express+cookie-parser:签名机制深入剖析(ok)

    个人总结:这篇文章讲解了express框架种cookie的使用,需要引用cookie-parser这个包.读完这篇文章需要10分钟. 摘选自网络 文章导读 cookie-parser是Express的 ...

  5. Zookeeper入门-Java版本HelloWorld例子

    上一篇介绍了,Zookeeper的基本概念,怎么启动,怎么解决可能遇到的几个问题.本篇,根据网上代码,整理了一个例子,Zookeeper的HelloWorld. 下面这个代码,还是比较简单的,核心类就 ...

  6. MySQL auttoReconnect

    com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from ...

  7. [Poi] Use Poi to Build an Index.js with Modern JavaScript Features

    Poi can easily launch an index.js file simply by running the poi command. This will launch a dev-ser ...

  8. [Python] Accessing Array Elements

    NumPy Reference: Indexing Note: Indexing starts at 0 (zero). def slicing(): a = np.random.rand(5,4) ...

  9. android YUV Sensor配置Camera应用的flash auto菜单

    请在Config.ftbl.flashlight.h (mediatek\custom\common\hal\flashlight\src)中. 将全部的两处凝视掉的code: //CameraPar ...

  10. JSP编程技术5-购物车的实现-session会话对象

    首先十分感谢大家对我的文章的支持,我是个刚刚才找到自己方向的在校大学生,当然我的知识和能力有限,眼下正在努力恶补学习中.当我看到自己首次发表到CSDN首页的文章才几个小时阅读量就超过了100时,对我来 ...