Dinic算法----最大流常用算法之一
——没有什么是一个BFS或一个DFS解决不了的;如果有,那就两个一起。
最大流的$EK$算法虽然简单,但时间复杂度是$O(nm^2)$,在竞赛中不太常用。
竞赛中常用的$Dinic$算法和$SAP$,其实也不太难。
那么,$Dinic$算法到底是什么呢?
多路增广
$Dinic$算法最核心的内容就是多路增广。
沿着$EK$算法的过程:
我们有一个图,如图一。
按照套路,我们先$BFS$,找$S-T$最短路。所有的距离标号都画在了图二上($EK$算法可能用不到,但$Dinic$用得到)。
假设我们选的是$S-3-T$这条路,增广。。。(如图三,绿色)
然后我们再来一遍$BFS$。。。 等等!
细心的你可能也发现了,$S-1-T$也是一条$S-T$最短路。
那就增广吧!(如图四)
您可以检查一下,这时候没有长度为$2$的最短路了。
但EK算法不会这样。它会再笨拙地$BFS$一遍,这就浪费了不少时间。
所以说,多路增广是很重要的。
我们换一种思路,如果网络流在一个$DAG$上,还不用考虑回退边,你会怎么做?
这很简单,$dfs$就能解决。
至于回退边。。。再来一次$BFS-DFS$就好了啊。
还有一个优化:当前弧优化:
对于每个点,我可能在一次$BFS$之后$DFS$多次。那么它出发的边所到的点里, 有些点出发已经满流。
这样, 我就可以每个点记录一个当前弧, 表示这次$DFS$它最后$DFS$到哪条弧,下次$DFS$它的时候就从这条弧开始。
这样,我就可以保证每条边在一次$DFS$中满流后不会再遍历。
这样的复杂度。。。理论上最坏是$O(n^2m)$,但这上界很松。
附代码!
int n; struct Dinic{
struct Edge{
int from, to;
LL cap, flow;
Edge(int f = -, int t = -, LL c = )
:from(f), to(t), cap(c), flow()
{}
}edges[MAXM];
int next[MAXM], cnt;
int pre[MAXN], dis[MAXN];
int cur[MAXN]; //当前弧
Dinic()
{
memset(pre, -, sizeof(pre));
cnt = ;
}
void addedge(int f, int t, LL c)
{
edges[cnt] = Edge(f, t, c);
next[cnt] = pre[f];
pre[f] = cnt++;
edges[cnt] = Edge(t, f, );
next[cnt] = pre[t];
pre[t] = cnt++;
}
queue<int> Q;
bool BFS(int s, int t)
{
while(!Q.empty()) Q.pop();
memset(dis, -, sizeof(dis));
dis[s] = ;
Q.push(s);
while(!Q.empty())
{
int u = Q.front(); Q.pop();
for(int i = pre[u]; i >= ; i = next[i]) if(edges[i].cap > edges[i].flow)
{
int v = edges[i].to;
if(dis[v] >= ) continue;
dis[v] = dis[u] + ;
if(v == t) return true;
Q.push(v);
}
}
return false;
}
LL DFS(int now, int t, LL maxflow) //当前在now,汇点t
{ //最大可以提供maxflow的流量
if(now == t) return maxflow;
int ret = ;
for(int i = cur[now] != - ? cur[now] : pre[now]; i >= ; i = next[i]) if(edges[i].cap > edges[i].flow)
{
int v = edges[i].to;
if(dis[v] != dis[now] + ) continue;
int l = DFS(v, t, min(edges[i].cap - edges[i].flow, maxflow - ret));
ret += l;
edges[i].flow += l;
edges[i^].flow -= l;
cur[now] = i;
if(ret == maxflow) return ret;
}
cur[now] = -;
return ret;
}
LL solve(int s, int t)
{
int res = ;
while(BFS(s,t))
{
memset(cur, -, n * sizeof(int));
res += DFS(s, t, inf);
}
return res;
}
};
Dinic
代码可能有错,烦请指出。谢谢。
另外,如果有人知道些好用的画图软件麻烦推荐一下。用windows自带画图太累了。
Dinic算法----最大流常用算法之一的更多相关文章
- POJ1273 网络流-->最大流-->模板级别-->最大流常用算法总结
一般预流推进算法: 算法思想: 对容量网络G 的一个预流f,如果存在活跃顶点,则说明该预流不是可行流. 预流推进算法就是要选择活跃顶点,并通过它把一定的流量推进到它的邻接顶点,尽可能将正的赢余减少为0 ...
- 算法模板——Dinic网络最大流 2
实现功能:同Dinic网络最大流 1 这个新的想法源于Dinic费用流算法... 在费用流算法里面,每次处理一条最短路,是通过spfa的过程中就记录下来,然后顺藤摸瓜处理一路 于是在这个里面我的最大流 ...
- ACM常用算法及练习(2)
ACM常用算法及练习 知识类型 重要度 容易度 应掌握度 典型题 其他 数据结构(5) 链表 ★★☆ ★★★ ★★☆ 栈 stack ★★★ ★★★ ★★★ HLoj120 ...
- ACM常用算法及练习(1)
ACM常用算法及练习 第一阶段:练经典常用算法,下面的每个算法给我打上十到二十遍,同时自己精简代码,因为太常用,所以要练到写时不用想,10-15分钟内打完,甚至关掉显示器都可以把程序打出来. 1.最短 ...
- ACM常用算法
数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 一维线段树 二维 ...
- 总结Objective-c常用算法
今天是星期天,想睡到10点起床,结果认为自己太奢侈了,不能这么做,于是把闹钟设置成了6:30:结果终于9:36醒了,起床,无缘无故迟了,好吧,就算太累了吧,周天就原谅自己一回.终于到了中午 ...
- 【小白学游戏常用算法】二、A*启发式搜索算法
在上一篇博客中,我们一起学习了随机迷宫算法,在本篇博客中,我们将一起了解一下寻路算法中常用的A*算法. 通常情况下,迷宫寻路算法可以使用深度优先或者广度优先算法,但是由于效率的原因,不会直接使用这些算 ...
- Atitit 编程语言常用算法attilax总结
Atitit 编程语言常用算法attilax总结 1. 编译算法分类and 数据操作算法.1 1.1. Tab driver stat 状态转换表格算法1 1.2. Nest case 词法分析 ...
- js算法之最常用的排序
引入 大学学习计算机语言的那几年,从c语言,到c++,再到数据结构JAVA..让我印象最深刻的还是最开始老师讲冒泡算法的时候,直到现在大四快毕业了我才渐渐通窍了.刚学前端的时候以为前端就是做出好看很炫 ...
随机推荐
- 10分钟教你用Python打造天气机器人+关键字自动回复+定时发送
01 前言 Hello,各位小伙伴.自上次我们介绍了Python实现天气预报的功能以后,那个小程序还有诸多不完善的地方,今天,我们再次来完善一下我们的小程序.比如我们想给机器人发“天气”等关键字,它就 ...
- 类型转换:static_cast、reinterpret_cast等
一.隐式类型转换 系统自动进行,不需要程序开发人员介入. int m = 3 + 45.6;// 48 把小数部分截掉,也属于隐式类型转换的一部分 double b = 3 + 45.6; // 48 ...
- Bootstrap-datepicker日期时间选择器的简单使用
日期时间选择器 目前,bootstrap有两种日历.datepicker和datetimepicker,后者是前者的拓展. Bootstrap日期和时间组件: 使用示例: 从左到右依次是十年视图.年视 ...
- shell-007:数据库备份,本地保留7天,远程机器保留一个月
## #!/bin/bash d1=`date +%w` # 以周几有变量 d2=`date +%d` # 以每月第几天为变量 local_bakdir=/bak/mysql # 本地备份目录 rem ...
- Java NIO学习与记录(七): Reactor单线程模型的实现
Reactor单线程模型的实现 一.Selector&Channel 写这个模型需要提前了解Selector以及Channel,之前记录过FileChannel,除此之外还有以下几种Chann ...
- 关闭mac自带apache的启动。
关闭mac自带apache的启动. sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist 如果哪天 ...
- Python离线安装依赖包
1.制作requirement.txt pip freeze > requirement.txt 2.下载离线Pytho安装包 pip download -r requirement.txt - ...
- 第3章—高级装配—bean的作用域
bean的作用域 bean的默认作用域 Spring定义了多种作用域,可以基于这些作用域创建bean,包括: 单例(Singleton):在整个应用中,只创建bean的一个实例. 原型(Prototy ...
- codeblocks中文编码问题
其实这是老调重弹的问题了,在windows下面出现中文乱码大多都是编码格式的问题不一致的问题,最简单的就是uft-8和gbk冲突的问题.如果一个文件本来是以utf-8存的,但是以gbk打开,当然会出现 ...
- Hadoop Hive概念学习系列之hive三种方式区别和搭建、HiveServer2环境搭建、HWI环境搭建和beeline环境搭建(五)
说在前面的话 以下三种情况,最好是在3台集群里做,比如,master.slave1.slave2的master和slave1都安装了hive,将master作为服务端,将slave1作为服务端. 以 ...