前置知识

网络最大流入门

前言

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. Java SpringMvc Jar包下载及部署方式_转载

    本次来记录一下关于 springmvc jar包的下载以及部署 首先登陆   http://repo.spring.io/release/org/springframework/spring/到里面我 ...

  2. Mojom IDL and Bindings Generator

    Mojom IDL and Bindings Generator This document is a subset of the Mojo documentation. Contents Overv ...

  3. ES6学习笔记(十二)异步解决方案Promise

    1.Promise 的含义 Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大.它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了P ...

  4. luoguP1419 寻找段落(二分答案+单调队列)

    题意 给定一个长度为n的序列a1~an,从中选取一段长度在s到t之间的连续一段使其平均值最大.(n<=100000) 题解 二分答案平均值. judge时把每一个a[i]-mid得到b[i] 在 ...

  5. poj 3613 Cow Relays(矩阵的图论意义)

    题解 用一个矩阵来表示一个图的边的存在性,即矩阵C[i,j]=1表示有一条从i到j的有向边C[i,j]=0表示没有从i到j的边.这个矩阵的k次方后C[i,j]就表示有多少条从i到j恰好经过k条边的路径 ...

  6. 对GPDB查询计划的Motion结点的理解

    GPDB在进行join查询时,可能会产生Motion结点 根据官方文档,总共有这几种Motion: redistribute 重分布(用hash取模的方法把join字段重分布到各个segment,相当 ...

  7. 火狐不支持innerText属性,只支持innerHTML属性

    做的一个js的小程序放到火狐上用不了了,原因是innerText不是标准属性,换成innerHTML属性就好,但是可能需要把html标签给去掉

  8. hdu 1695 GCD (欧拉函数、容斥原理)

    GCD Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  9. webpack03

    index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  10. spring-cloud-netflix集成的服务

    1.Ribbon Ribbon is a client side IPC library that is battle-tested in cloud. It provides the followi ...