省赛在即!最大流问题回顾学习!!DInic
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的更多相关文章
- Asp.net Form登陆认证的回顾学习
asp.net网站中,我最常用的就是Form认证了,在实现登陆时,利用Form认证实现用户的访问权限,哪些页面是可以匿名登陆,哪些页面需要认证后才能访问,哪些页面不能访问等等权限.我还可在登陆时,使用 ...
- response与request回顾学习
一.response response是servlet.service方法的一个参数,它的类型是javax.servlet.http.HttpServletResponse,在客户端每发出一个请求时, ...
- Mybatis的回顾学习
<!--id:statementId resultType:查询结果集的数据类型 parameterType:查询的入参 --> <selectid="getUserByI ...
- KMP回顾学习
记住这张图,getnext就是对一个已知的待匹配的串进行分析,nex[i]表示当a[i]匹配失败后我能跳到哪里,继续尝试匹配,而不是每一次失败都从头再来,先来看看代码 const int maxn = ...
- 网络流学习 - dinic
推荐博客:https://www.cnblogs.com/SYCstudio/p/7260613.html#4246029
- 杭电1532----Drainage Ditches『最大流』
/* 网络流的最大流问题 刚学习Dinic算法.模版题 */ #include <cstring> #include <cstdio> #include <queue&g ...
- 学习笔记 --- 最大流Dinic算法
为与机房各位神犇同步,学习下网络流,百度一下发现竟然那么多做法,最后在两种算法中抉择,分别是Dinic和ISAP算法,问过 CA爷后得知其实效率上无异,所以决定跟随Charge的步伐学习Dinic,所 ...
- Python小白的数学建模课-A3.12 个新冠疫情数模竞赛赛题与点评
新冠疫情深刻和全面地影响着社会和生活,已经成为数学建模竞赛的背景帝. 本文收集了与新冠疫情相关的的数学建模竞赛赛题,供大家参考,欢迎收藏关注. 『Python小白的数学建模课 @ Youcans』带你 ...
- POJ1459Power Network(dinic模板)
Power Network Time Limit: 2000MS Memory Limit: 32768K Total Submissions: 25832 Accepted: 13481 D ...
随机推荐
- [Centos] ERROR: Could not find useradd in chroot, maybe the install failed?
[mockbuild at localhost ~]$ mock -r centos-5-x86_64-testdev.cfg initinitcleanprepThis may take a whi ...
- BZOJ1088或洛谷2327 [SCOI2005]扫雷
BZOJ原题链接 洛谷原题链接 很容易发现答案就只有\(0,1,2\)三种答案,而且只要知道第一个格子是否有雷就可以直接顺推下去了. 所以我们跑一次首位有雷,跑一次首位无雷判断是否可行即可. #inc ...
- 简单的node 服务端 响应get,返回json数据;
原文:http://blog.csdn.net/xn_28/article/details/50837019 const http = require('http'); const hostname ...
- kdump 调试手段
kdump是在系统崩溃的时候用来转储内存运行参数的一个工具和服务,打个比方,如果系统一旦崩溃那么正常的内核就没有办法工作了,在这个时候将由kdump产生一个用于capture当前运行信息的内核,该内核 ...
- Linux学习笔记:Shell脚本学习
概念 真正能够控制计算机硬件(CPU.内存.显示器等)的只有操作系统内核(Kernel),图形界面和命令行只是架设在用户和内核之间的一座桥梁. 由于安全.复杂.繁琐等原因,用户不能直接接触内核(也没有 ...
- TabControl中显示和隐藏TabPage页
在使用TabControl控件时,希望隐藏其中某个选项卡(即TabPage).TabPage类明明提供了一个Hide方法,用在代码中却没有任何效果,甚是奇怪.无奈之余,只好考虑另辟途径 方法一: 设置 ...
- MySQL参数优化:back_log
* 修改back_log参数值:由默认的50修改为500.(每个连接256kb, 占用:125M) back_log=500 查看mysql 当前系统默认back_log值,命令: show vari ...
- thymeleaf使用基础教程
thymeleaf 是新一代的模板引擎,在spring4.0中推荐使用thymeleaf来做前端模版引擎. thymeleaf介绍 简单说, Thymeleaf 是一个跟 Velocity.FreeM ...
- js监听微信、支付宝返回,后退、上一页按钮事件
$(function(){ pushHistory(); window.addEventListener("popstate", function(e) { alert(" ...
- python3 提示 name ‘reload’ is not defined
import importlib importlib.reload(sys)