Dinic是很好的算法,但是我还是从ek算法复习起步

面对最大流问题,印象最深的就是反向边的思想,他给我们提供了反悔的机会,其实现在放到实际上来想,可以相当于两边的水都流了这条边,只是方向不一样,放到程序上,就是添加反向边。

ek算法是基础的算法,思想也比较简单,就是先用bfs去寻找一波可行的1  到  n 的最大流,然后记录每一个经过的结点的前驱,在调用ek算法建立反向边,时间上面也是很费时,所以才有必要去学习Dinic算法及其优化的版本,这里就不粘贴我的ek算法的代码了……

果然是温故而知新,复习了一晚上Dinic算法,有对他有了新的理解和认识,相对于ek算法,dinic算法的优化真的是非常的好——当前弧优化

#include <iostream>
#include <string.h>
#include <cstdio>
#include <queue>
#define inf 0xfffffff
using namespace std;
const int maxn = 220;//最大的结点数量
const int maxm = 4e4 + 4e2;//边的数量
int n,m;
struct node{
int pre;
int to,cost;
}e[maxm];
int id[maxn],cnt;
int flor[maxn];
void init()
{
memset(id,-1,sizeof(id));
cnt = 0;
}
int cur[maxn];
void add(int from,int to,int cost)
{
e[cnt].to = to;
e[cnt].cost = cost;
e[cnt].pre = id[from];
id[from] = cnt++;
swap(from,to);
e[cnt].to = to;
e[cnt].cost = 0;
e[cnt].pre = id[from];
id[from] = cnt++;
}

上面都是基本的存储结构,链式前向星存储,反向边的建立,层数的记录

先面整体观看一下Dinic算法

int Dinic(int s,int t)
{
int ret = 0;
while(bfs(s,t))//进行分层预处理
{
for(int i = 1;i <= n;i++)
{
cur[i] = id[i];
}
ret += dfs(s,t,inf);//dfs寻找最大增广路
}
return ret;
}

bfs进行分层处理,dfs进行最大增广路的寻找,cur数组时dfs中优化的一个关键,后面会提及

先来看看bfs分层处理

int bfs(int s,int t)
{
queue<int>q;
while(q.size())q.pop();
memset(flor,0,sizeof(flor));
flor[s] = 1;
q.push(s);
while(q.size())
{
int now = q.front();
q.pop();
for(int i = id[now];~i;i = e[i].pre)
{
int to = e[i].to;
int cost = e[i].cost;
if(flor[to] == 0/*冲当了vis*/ && cost > 0/*还有流量*/ )
{
flor[to] = flor[now] + 1;
q.push(to);
if(to == t)return 1;//分层到终点结束立即返回
}
}
}
return 0;
}

根据边的关系flor数组还充当vis数组,进行层级标记,为后续的dfs做准备,bfs何时返回呢要么时到了中点返回1,要么是到不了终点返回0

精彩的时dfs,当前弧的优化思想太厉害太厉害了

int dfs(int s,int t,int value)//起点,终点,当前流量
{
//寻找增广路
int ret = value;
if(s == t || value == 0)return value;//要么是路通了,要么是没路了
int a;
//找不到t了,因为到t的边流量都变成了0!! /*
  优化的时候记录优化到哪条边了
所以对于每一条边我只会访问一次
*/
for(int &i = cur[s];~i;i = e[i].pre)
{
int to = e[i].to;
if(flor[to] == flor[s] + 1 && (a = dfs(to,t,min(ret,e[i].cost))))
{
e[i].cost -= a;//对于这条边的优化操作
e[i^1].cost += a;
ret -= a;//最后返回的是ret -= a 所以我们是记录了a的
if(!ret)break;//ret == 0时
/*
ret记录了s到to的最大流量值a呢是to到t的最大流量
当ret - a == 0 的时候就可以结束了,往前返回的是value值,进行后续边的优化
*/ /*
为什么不相等的时候不会退出呢??
不相等,也就是ret > a,这是后前面的路都至少还有ret - a的残量,可以继续dfs进行优化更新
*/
}
}
if(ret == value)flor[s] = 0;//中间结点遍历了所有的边,得到的结果是无路(流量),所以标志中间结点s废掉
return value - ret;
}

先来放一张我画的惨图

没错,一开始我对初始传参dfs(s,t,inf)传入inf不是太理解,第一次调用什么都没有连同,所以可流量时无限大的,也为了结下的递归做了铺垫

然后dfs的递归设置结束的条件1.找到了2.当前可流量变成了零也就没必要继续找了不是??

当前弧优化的经典就是cur数组,也就是id数组的副本,记录了边的信息,C++的引用确保了对于这个点的边信息我只会dfs一次,不会重复dfs这样就大大的节约了时间

然后a接受的时to 到 t 的最大流量,返回之后层层进行边和反向边的更新ret -= a时什么意思呢??首先来看看ret表示的什么吧递归进来的时候ret和value都表示的时s 到 to的最大可流量,而a表示的时to 到 t 的最大流量,我们要对to前面的边进行优化,所以ret -= a表示的时s 到 to的那些点还有没有可流能力如果ret = 0那就不可再流直接返回,反之可以再留,就继续根据cur数组进行后面边的查询,直到查询结束,跳出的时候你可以判断一下如果当前s点后没有一条就可以标记s点为费点接下来的dfs回溯优化不会在考虑s点了,也是一个小小的优化吧

到此,Dinic算法就告于段落了~~

——————————————————————————————————————————————————

加油!!

省赛在即!最大流问题回顾学习!!DInic的更多相关文章

  1. Asp.net Form登陆认证的回顾学习

    asp.net网站中,我最常用的就是Form认证了,在实现登陆时,利用Form认证实现用户的访问权限,哪些页面是可以匿名登陆,哪些页面需要认证后才能访问,哪些页面不能访问等等权限.我还可在登陆时,使用 ...

  2. response与request回顾学习

    一.response response是servlet.service方法的一个参数,它的类型是javax.servlet.http.HttpServletResponse,在客户端每发出一个请求时, ...

  3. Mybatis的回顾学习

    <!--id:statementId resultType:查询结果集的数据类型 parameterType:查询的入参 --> <selectid="getUserByI ...

  4. KMP回顾学习

    记住这张图,getnext就是对一个已知的待匹配的串进行分析,nex[i]表示当a[i]匹配失败后我能跳到哪里,继续尝试匹配,而不是每一次失败都从头再来,先来看看代码 const int maxn = ...

  5. 网络流学习 - dinic

    推荐博客:https://www.cnblogs.com/SYCstudio/p/7260613.html#4246029

  6. 杭电1532----Drainage Ditches『最大流』

    /* 网络流的最大流问题 刚学习Dinic算法.模版题 */ #include <cstring> #include <cstdio> #include <queue&g ...

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

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

  8. Python小白的数学建模课-A3.12 个新冠疫情数模竞赛赛题与点评

    新冠疫情深刻和全面地影响着社会和生活,已经成为数学建模竞赛的背景帝. 本文收集了与新冠疫情相关的的数学建模竞赛赛题,供大家参考,欢迎收藏关注. 『Python小白的数学建模课 @ Youcans』带你 ...

  9. POJ1459Power Network(dinic模板)

    Power Network Time Limit: 2000MS   Memory Limit: 32768K Total Submissions: 25832   Accepted: 13481 D ...

随机推荐

  1. PAT 1016 部分A+B(15)(C++&JAVA&&Python)

    1016 部分A+B(15 分) 正整数 A 的"D​A​​(为 1 位整数)部分"定义为由 A 中所有 D​A​​ 组成的新整数 P​A​​.例如:给定 A=3862767,D​ ...

  2. 解决CentOS7-python-pip安装失败

    Pip介绍 pip 是一个安装和管理 Python 包的工具,python安装包的工具有easy_install, setuptools, pip,distribute.使用这些工具都能下载并安装dj ...

  3. socket 长连接

    实现: 长连接的维持,是要客户端程序,定时向服务端程序,发送一个维持连接包的. 如果,长时间未发送维持连接包,服务端程序将断开连接. 服务端: 由于客户端会定时(keepAliveDelay毫秒)发送 ...

  4. linux(centOS7,mini),python环境的搭建

    今天想试一试python在linux下的工作,在vmware中安装了centOS7版本的linux,先前装过一个带GUI的,但是感觉在虚拟机理跑的太慢,干脆直接装一个最精简的mini版,试一下ifco ...

  5. 为什么要选择OMP之合规性

  6. PHP字符串大小写转换函数

    string strtolower(string $str) 将字符串转换为小写 string strtoupper(string $str) 将字符串转换为大写 $str1 = 'html'; $s ...

  7. python ui学习过程,使用pyqt5实现

    首先安装pyqt5的包,然后打开notebook就可以编写了.当然这样编写,也可以用designer进行. 它是pyqt5-tools的一个exe软件,\Anaconda3\Lib\site-pack ...

  8. delphi 中的win32 以外到平台的字符串处理一定慢吗?(转载)

    原始连接:http://rvelthuis.blogspot.tw/2018/01/strings-on-other-platforms-than-32-bit.html Strings too sl ...

  9. 初识kbmmw 中的ORM

    在kbmmw 5.02.1 中,加入了ORM 的功能(这里可能和其他语言的定义不完全一样),我们就简单的认为 它就是一个类与数据库的转换吧.今天就先介绍一下如何通过kbmmw 的ORM 功能,实现类与 ...

  10. chmod / chown /chattr

    显示了七列信息,从左至右依次为:权限.文件数.归属用户.归属群组.文件大小.创建日期.文件名称 d :第一位表示文件类型 d 文件夹 - 普通文件 l 链接 b 块设备文件 p 管道文件 c 字符设备 ...