Dinic当前弧优化 模板及教程
在阅读本文前,建议先自学最大流的Ek算法。
引入
Ek的核心是执行bfs,一旦找到增广路就停下来进行增广。换言之,执行一遍BFS执行一遍DFS,这使得效率大大降低。于是我们可以考虑优化。
核心思路
在一次BFS中,找到的增广路可能不止一条,这时我们可以本着“尽量少进行BFS”的想法,在一次bfs后把所有能增广的路径全部增广。
具体怎么做呢?
仍然是:
while(bfs(源点,汇点)) dfs();
每次bfs标记出每个点的“深度”,也就是距离源点的长度。我们将得到的新图称作分层图。接下来我们在分层图上进行增广,把能增广的路径全部增广。
其它部分和Ek大体相同。
关于当前弧优化
其实是一个很强的优化
每次增广一条路后可以看做“榨干”了这条路,既然榨干了就没有再增广的可能了。但如果每次都扫描这些“枯萎的”边是很浪费时间的。那我们就记录一下“榨取”到那条边了,然后下一次直接从这条边开始增广,就可以节省大量的时间。这就是当前弧优化
具体怎么实现呢,先把链式前向星的head数组复制一份,存进cur数组,然后在cur数组中每次记录“榨取”到哪条边了。
Code
//by floatiy
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int MAXN = + ;
const int MAXM = + ;
const int INF = 1e9;
int n,m;
int s,t;//源点 汇点
int maxflow;//答案
struct Edge {
int next;
int to,flow;
} l[MAXM << ];
int head[MAXN],cnt = ;
int deep[MAXN],cur[MAXN];//deep记录bfs分层图每个点到源点的距离
queue <int> q;
inline void add(int x,int y,int z) {
cnt++;
l[cnt].next = head[x];
l[cnt].to = y;
l[cnt].flow = z;
head[x] = cnt;
return;
}
int min(int x,int y) {
return x < y ? x : y;
}
int dfs(int now,int t,int lim) {//分别是当前点,汇点,当前边上最小的流量
if(!lim || now == t) return lim;//终止条件
// cout<<"DEBUG: DFS HAS BEEN RUN!"<<endl;
int flow = ;
int f;
for(int i = cur[now]; i; i = l[i].next) {//注意!当前弧优化
cur[now] = i;//记录一下榨取到哪里了
if(deep[l[i].to] == deep[now] + //谁叫你是分层图
&& (f = dfs(l[i].to,t,min(lim,l[i].flow)))) {//如果还能找到增广路
flow += f;
lim -= f;
l[i].flow -= f;
l[i ^ ].flow += f;//记得处理反向边
if(!lim) break;//没有残量就意味着不存在增广路
}
}
return flow;
}
bool bfs(int s,int t) {
for(int i = ; i <= n; i++) {
cur[i] = head[i];//拷贝一份head,毕竟我们还要用head
deep[i] = 0x7f7f7f7f;
}
while(!q.empty()) q.pop();//清空队列 其实没有必要了
deep[s] = ;
q.push(s);
while(!q.empty()) {
int tmp = q.front();
q.pop();
for(int i = head[tmp]; i; i = l[i].next) {
if(deep[l[i].to] > INF && l[i].flow) {//有流量就增广
//deep我赋的初值是0x7f7f7f7f 大于 INF = 1e9)
deep[l[i].to] = deep[tmp] + ;
q.push(l[i].to);
}
}
}
if(deep[t] < INF) return true;
else return false;
}
void dinic(int s,int t) {
while(bfs(s,t)) {
maxflow += dfs(s,t,INF);
// cout<<"DEBUG: BFS HAS BEEN RUN!"<<endl;
}
}
int main() {
cin>>n>>m;//点数边数
cin>>s>>t;
int x,y,z;
for(int i = ; i <= m; i++) {
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,);
}
// cout<<"DEBUG: ADD FININSHED!"<<endl;
dinic(s,t);
printf("%d",maxflow);
return ;
}
Dinic当前弧优化 模板及教程的更多相关文章
- ARC085E(最小割规划【最大流】,Dinic当前弧优化)
#include<bits/stdc++.h>using namespace std;typedef long long ll;const ll inf=0x3f3f3f3f;int cn ...
- P3376 网络流-最大流模板题(Dinic+当前弧优化)
(点击此处查看原题) Dinic算法 Dinic算法相对于EK算法,主要区别在于Dinic算法对图实现了分层,使得我们可以用一次bfs,一次dfs使得多条增广路得到增广 普通的Dinic算法已经可以处 ...
- [Poj2112][USACO2003 US OPEN] Optimal Milking [网络流,最大流][Dinic+当前弧优化]
题意:有K个挤奶机编号1~K,有C只奶牛编号(K+1)~(C+K),每个挤奶机之多能挤M头牛,现在让奶牛走到挤奶机处,求奶牛所走的最长的一条边至少是多少. 题解:从起点向挤奶机连边,容量为M,从挤奶机 ...
- HDU 4280 Island Transport(dinic+当前弧优化)
Island Transport Description In the vast waters far far away, there are many islands. People are liv ...
- 【Luogu】P1231教辅的组成(拆点+Dinic+当前弧优化)
题目链接 妈耶 我的图建反了两次 准确的说是有两个地方建反了,然后反上加反改了一个小时…… 知道为什么要拆点吗? 假设这是你的图 左边到右边依次是超级源点 练习册 书 答案 ...
- 网络流小记(EK&dinic&当前弧优化&费用流)
欢 迎 来 到 网 络 瘤 的 世 界 什么是网络流? 现在我们有一座水库,周围有n个村庄,每个村庄都需要水,所以会修水管(每个水管都有一定的容量,流过的水量不能超过容量).最终水一定会流向唯一一个废 ...
- 最大流加强 dinic+当前弧优化
qyy开始练习网络流啦 , 啊 ,蒟蒻只会套版 ,很裸的题 , 我连题都不想发了 ,可以参考我的代码(虽然我也是看的别人的 #include <iostream> #include < ...
- 网络流 - dinic + 当前弧优化【代码】
这是初学网络流的时候从<算法竞赛进阶指南>抄下来的一份代码,自己理解的也不是很透彻. 注意,边要从 \(1\) 开始计,不然直接 \(xor\) 运算的话取反边会直接炸掉. #includ ...
- 网络流--最大流--Dinic模板矩阵版(当前弧优化+非当前弧优化)
//非当前弧优化版 #include <iostream> #include <cstdio> #include <math.h> #include <cst ...
随机推荐
- LeetCode 976. Largest Perimeter Triangle (三角形的最大周长)
题目标签:Array 题目给了我们一个 边长的 array, 让我们找出 最大边长和的三角形,当然前提得是这三条边能组成三角形.如果array 里得边长组成不了三角形,返回0. 最直接的理解就是,找到 ...
- 浏览器的多线程和js的单线程--前端易混淆知识科普(一)
问题:js是单线程的,页面是从上往下加载的,那么是不是第一个js没加载完成,第二个js就不加载?然后,引申出来一个问题就是,那css和图片呢?这之间的加载有相互影响吗? 1.什么是线程?什么是进程?什 ...
- 第14章4节《MonkeyRunner源代码剖析》 HierarchyViewer实现原理-装备ViewServer-port转发
在初始化HierarchyViewer的实例过程中,HierarchyViewer会调用自己的成员方法setupViewServer来把ViewServer装备好,那么我们这里先看下这种方法: 39 ...
- click事件触发也有失灵的时候?
今天做了个手机页面,点击某个按钮->弹出菜单,再点击菜单以外的任意位置->关闭菜单,在其他浏览器里面没有问题,但是在IOS浏览器中并不会关闭. 网上解决这个bug的帖子很多,这篇帖子主要是 ...
- sqlserver 触发器实例代码
定义: 何为触发器?在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序.触发器是一个特殊的存储过程. 常见的触发器有三种:分别应用于Insert , Update ...
- InfluxDB 分布式时间序列数据库环境搭建——据qcon大会2016qiniu说集群很坑且闭源了
InfluxDB 分布式时间序列数据库环境搭建 1. 环境说明 Ubuntu14.04 + influxDB V0.10.1 搭建3个节点的分布式数据库,副本数量2,各节点之间自动进行数据备份并 ...
- hdu 6119 小小粉丝度度熊(尺取)
小小粉丝度度熊 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- jeesite ckeditor数据库 HTML 被编码 的问题解决
public abstract class BaseController { /** * 初始化数据绑定 * 1. 将所有传递进来的String进行HTML编码,防止XSS攻击 * 2. 将字段中Da ...
- 北大zhw大神bzoj1756代码
#include <cmath> #include <cstdio> #include <cstdlib> #include <iostream> #i ...
- 异常强大的Markdown编辑插件-Markdown Preview Enhanced
最近使用Markdown写作,了解到以下这些Markdown写作工具 MaHua 在线markdown编辑器 百度搜索Markdown时,它排在非常靠前的位置 马克飞象- 专为印象笔记打造的Markd ...