摘自https://www.cnblogs.com/SYCstudio/p/7260613.html

网络流定义 

  在图论中,网络流(Network flow)是指在一个每条边都有容量(Capacity)的有向图分配流,使一条边的流量不会超过它的容量。通常在运筹学中,有向图称为网络。顶点称为节点(Node)而边称为弧(Arc)。一道流必须匹配一个结点的进出的流量相同的限制,除非这是一个源点(Source)──有较多向外的流,或是一个汇点(Sink)──有较多向内的流。一个网络可以用来模拟道路系统的交通量、管中的液体、电路中的电流或类似一些东西在一个结点的网络中游动的任何事物。————维基百科

 最大流

  正如可以通过将道路交通图模型化为有向图来找到从一个城市到另一个城市之间的最短路径,我们也可以将一个有向图看做是一个“流网络”并使用它来回答关于物料流动方面的问题。设想一种物料从产生它的源结点经过一个系统,流向消耗该物料的汇点这样一个过程。源结点以某种稳定的速率生成物料,汇点则以同样的速率消耗物料。从直观上看,物料在系统中任何一个点上的“流量”就是物料移动的速率。这种流网络可以用来建模很多实际问题,包括液体在管道中的流动、装配线上部件的流动、电网中电流的流动和通信网络中信息的流动。我们可以把流网络中每条有向边看做是物料的一个流通通道。每条通道有限定的容量,是物料流经该通道时的最大速率,如一条管道每小时可以流过200加仑的液体。流网络中的结点则是通道的连接点。除了源结点和终结点外,物料在其他结点上只是流过,并不积累或聚集。换句话说,物料进入一个结点速率必须与其离开该结点的速率相等。这个性质称为“流量守恒”,这里的流量守恒与Kirchhoff电流定律等价。在最大流问题中,我们希望在不违反任何容量限制的情况下,计算出从源结点运送物料到汇点的最大速率。这是与流网络有关的所有问题中最简单的问题之一(????).,这个问题可以由高效的算法解决。而且,最大流算法中的一些基本技巧可以用来解决其他网络流问题。————《算法导论》

Dinic算法

  定义:

  源点:只有流出去的点
  汇点:只有流进来的点
  流量:一条边上流过的流量
  容量:一条边上可供流过的最大流量
  残量:一条边上的容量-流量

几个基本性质

基本性质一:

对于任何一条流,总有流量<=容量

这是很显然的

基本性质二

对于任何一个不是源点或汇点的点u,总有

∑p∈Ek[p][u]==∑q∈Ek[u][q](其中k[i][j]表示i到j的流量)∑p∈Ek[p][u]==∑q∈Ek[u][q](其中k[i][j]表示i到j的流量)

这个也很显然,即一个点(除源点和汇点)的入流和出流相等

基本性质三

对于任何一条有向边(u,v),总有

k[u][v]==−k[v][u]k[u][v]==−k[v][u]

这个看起来并不是很好理解,它的意思就是一条边的反边上的流是这条边的流的相反数,可以这么想,就是如果有k[u][v]的流从u流向v,也就相当于有-k[v][u]的流从v流向u。这条性质非常重要。

网络流最大流的求解(Ford-Fulkerson算法)

网络流的所有算法都是基于一种增广路的思想,其基本步骤如下:

1.找到一条从源点到汇点的路径,使得路径上任意一条边的残量>0(注意是大于而不是大于等于,这意味着这条边还可以分配流量),这条路径便称为增广路
2.找到这条路径上最小的F[u][v](我们设F[u][v]表示u->v这条边上的残量即剩余流量),下面记为flow
3.将这条路径上的每一条有向边u->v的残量减去flow,同时对于起反向边v->u的残量加上flow
4.重复上述过程,直到找不出增广路,此时我们就找到了最大流

这个算法是基于增广路定理(Augmenting Path Theorem): 网络达到最大流当且仅当残留网络中没有增广路

在寻找增广路的过程中,如果我们没有建反边,那么有时候会发现找出来的路径与实际上的最大流不同,我们建这个反边是为了将原先得到的流推回去,从而得到新的流,就是给了我们反悔的机会。

这种朴素的FF算法在某种情况下可能非常低效,比如这个栗子


我们一眼可以看出最大流是999(s->v->t)+999(s->u->t),但如果程序采取了不恰当的增广策略:s->v->u->t

我们发现中间会加一条u->v的边

而下一次增广时:

若选择了s->u->v->t

然后就变成

如果边上的容量更大,这个算法可能会更加低效,这时引入Dinic算法

Dinic算法

为Dinic算法引入了一个叫做分层图的概念。具体就是对于每一个点,我们根据从源点开始的bfs序列,为每一个点分配一个深度,然后我们进行若干遍dfs寻找增广路,每一次由u推出v必须保证v的深度必须是u的深度+1。

Dinic算法总结

1、首先进行bfs分层网络
2、进行dfs多路增广,并且记录残量网络和流
量。
3、重复上述过程直到不存在从s到t的路径为
止。将所有dfs的结果累加起来就是答案。将
每一次的增广路效果叠加起来就是图上每条
边的流量。

例题:HDU-3549 Flow Problem http://acm.hdu.edu.cn/showproblem.php?pid=3549

 #include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define INF 0x3f3f3f3f
const ll MAXN = + ;
const ll MAXM = 1e3 + ;
const ll MOD = 1e9 + ;
const double pi = acos(-);
int cnt = -, head[MAXM], dis[MAXN], cur[MAXM];
int n, m;
struct edge
{
int to, value, net;
} e[MAXM << ]; ///共有n*2条边
void add(int from, int to, int value)
{ ///链式前向星
cnt++;
e[cnt].to = to;
e[cnt].value = value;
e[cnt].net = head[from];
head[from] = cnt;
}
int bfs(int st, int ed)
{ ///建立层次图
queue<int> que;
memset(dis, -, sizeof(dis));
dis[st] = ;
que.push(st);
while (!que.empty())
{
int x = que.front();
que.pop();
for (int i = head[x]; i > -; i = e[i].net)
{
int now = e[i].to;
if (dis[now] == - && e[i].value)
{
que.push(now);
dis[now] = dis[x] + ;
}
}
}
return dis[ed] != -;
}
int dfs(int x, int t, int maxflow)
{
if (x == t)
return maxflow;
int ans = ;
for (int i = cur[x]; i > -; i = e[i].net)
{ ///当前弧优化
int now = e[i].to;
if (dis[now] != dis[x] + || e[i].value == || ans >= maxflow)
continue;
cur[x] = i;
int f = dfs(now, t, min(e[i].value, maxflow - ans));
e[i].value -= f;
e[i ^ ].value += f; ///反向边加流量
ans += f;
}
if (!ans)
dis[x] = -; ///炸点优化
return ans;
}
int Dinic(int st, int ed)
{
int ans = ;
while (bfs(st, ed))
{
memcpy(cur, head, sizeof(head));
int k;
while ((k = dfs(st, ed, INF)))
ans += k;
}
return ans;
}
void init()
{
cnt=-;
memset(head,-,sizeof(head));
}
int main()
{
int t;
scanf("%d", &t);
for (int i = ; i <= t; i++)
{
init();
scanf("%d%d", &n, &m);
while (m--)
{
int u, v, t;
scanf("%d%d%d", &u, &v, &t);
add(u, v, t);
add(v, u, );
}
printf("Case %d: %d\n", i, Dinic(, n));
}
return ;
}

网络流(最大流-Dinic算法)的更多相关文章

  1. 网络流最大流——dinic算法

    前言 网络流问题是一个很深奥的问题,对应也有许多很优秀的算法.但是本文只会讲述dinic算法 最近写了好多网络流的题目,想想看还是写一篇来总结一下网络流和dinic算法以免以后自己忘了... 网络流问 ...

  2. [讲解]网络流最大流dinic算法

    网络流最大流算法dinic ps:本文章不适合萌新,我写这个主要是为了复习一些细节,概念介绍比较模糊,建议多刷题去理解 例题:codevs草地排水,方格取数 [抒情一下] 虽然老师说这个多半不考,但是 ...

  3. Power Network(网络流最大流 & dinic算法 + 优化)

    Power Network Time Limit: 2000MS   Memory Limit: 32768K Total Submissions: 24019   Accepted: 12540 D ...

  4. 网络流——最大流Dinic算法

    前言 突然发现到了新的一年什么东西好像就都不会了凉凉 算法步骤 建残量网络图 在残量网络图上跑增广路 重复1直到没有增广路(注意一个残量网络图要尽量把价值都用完,不然会浪费建图的时间) 代码实现 #i ...

  5. 网络流之最大流Dinic算法模版

    /* 网络流之最大流Dinic算法模版 */ #include <cstring> #include <cstdio> #include <queue> using ...

  6. 学习笔记 --- 最大流Dinic算法

    为与机房各位神犇同步,学习下网络流,百度一下发现竟然那么多做法,最后在两种算法中抉择,分别是Dinic和ISAP算法,问过 CA爷后得知其实效率上无异,所以决定跟随Charge的步伐学习Dinic,所 ...

  7. hdu-3572 Task Schedule---最大流判断满流+dinic算法

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3572 题目大意: 给N个任务,M台机器.每个任务有最早才能开始做的时间S,deadline E,和持 ...

  8. 最大流——Dinic算法

    前面花了很长时间弄明白了压入-重标记的各种方法,结果号称是O(V3)的算法测demo的时候居然TLE了一个点,看了题解发现所有人都是用Dinic算法写的,但它的复杂度O(V2E)明显高于前者,具体是怎 ...

  9. 求最大流dinic算法模板

    //最短增广路,Dinic算法 struct Edge { int from,to,cap,flow; };//弧度 void AddEdge(int from,int to,int cap) //增 ...

随机推荐

  1. Service Mesh服务网格清单

    Service Mesh服务网格清单 Istio Istio官网 Istio中文官网 Istio开源 无需太多介绍Service Mesh明日之星,扛把子,截止2019.11还有太多问题没解决 复杂性 ...

  2. 【ZooKeeper系列】3.ZooKeeper源码环境搭建

    前文阅读: [ZooKeeper系列]1.ZooKeeper单机版.伪集群和集群环境搭建 [ZooKeeper系列]2.用Java实现ZooKeeper API的调用 在系列的前两篇文章中,介绍了Zo ...

  3. 反射 API基本代码测试

    ReflectBean.java package com.xiaojian.basics.reflect; /** * 使用反射的测试类 */ public class ReflectBean { / ...

  4. ssh免密登陆和加密解密

    一 丶实现无密码的远程管理 1.生成公钥 私钥 [root@room9pc14 桌面]# ssh-keygen [root@room9pc14 桌面]# ls /root/.ssh/ 2.上传公钥到虚 ...

  5. JVM之堆的体系结构

    一.堆的体系结构 Heap 堆一个JVM 实例只存在一个堆内存,堆内存的大小是可以调节的.类加载器读取了类字节码文件后,需要把类.方法.常量.变最放到堆内存中,保存所有引用类型的真实信息,以便执行器执 ...

  6. 人群密度检测MCNN+CSRnet

    MCNN(简单理解): 三列卷积神经网络,分别为大中小三种不同尺度的卷积核,表示为L列(使用大尺度卷积核: 9*9, 7*7, 7*7,7*7), M(使用中等尺度卷积核: 7*7, 5*5, 5*5 ...

  7. ThreadLocal = 本地线程?

    一.定义 ThreadLocal是JDK包提供的,从名字来看,ThreadLocal意思就是本地线程的意思. 1.1 是什么? 要想知道他是个啥,我们看看ThreadLocal的源码(基于JDK 1. ...

  8. Could not find iPhone 6 simulator

    最近原来的老项目有点问题需要处理一下,运行启动命令,就报了如下错误,提示找不到iPhone 6 模拟器. react-native run-ios Owaiss-Mac:pdm owaisahmed$ ...

  9. vnpy源码阅读学习(4):自己写一个类似vnpy的UI框架

    自己写一个类似vnpy的界面框架 概述 通过之前3次对vnpy的界面代码的研究,我们去模仿做一个vn.py的大框架.巩固一下PyQt5的学习. 这部分的代码相对来说没有难度和深度,基本上就是把PyQt ...

  10. spark和strom优劣分析

    对于Storm来说:1.建议在那种需要纯实时,不能忍受1秒以上延迟的场景下使用,比如实时金融系统,要求纯实时进行金融交易和分析2.此外,如果对于实时计算的功能中,要求可靠的事务机制和可靠性机制,即数据 ...