【网络流相关】最大流的Dinic算法实现
Luogu P3376
由于\(EK\)算法求最大流时每一次只求一条增广路,时间复杂度会比较高。尽管实际应用中表现比较优秀,但是有一些题目还是无法通过。
那么我们就会使用\(Dinic\)算法实现多路增广。
算法的基本流程如下:
- \(BFS\)对图进行分层,求出终点所在的层数
- \(DFS\)对每一条增广路的信息进行更新
仅仅这样看,虽然一次\(BFS\)能找到多条最短增广路,但是信息的更新仍然是逐条增广路进行更新,效率上并没有太大变化。
所以我们需要下面的两个优化:
- 记录起点到节点\(P\)的流\(flow\)和节点\(P\)到终点的流\(used\)。若\(flow=used\),则不必再进行之后的\(DFS\)了,可以直接回溯。
- 使用一个\(cur\)数组复制链式前向星的\(head\)数组,在\(DFS\)时,\(cur\)数组记录当前处理的边的编号。下次\(DFS\)到这个节点时,可以直接从\(cur\)数组记录的那条边开始。
第二个优化我们称之为当前弧优化。
原理:每一条已经处理完毕的边,必然不能再容纳下更多的流了。
\(Dinic\)的时间复杂度是\(O(n^2m)\)。对于二分图匹配问题,\(Dinic\)的时间复杂度是\(O(m\sqrt n)\)
结合代码进行理解
#include<cstdio>
#include<queue>
using namespace std;
int n,m,num,cnt,u,v,head[20005],cur[20005],dis[20005],ans;
bool vis[20005];
struct data
{
int to,next,val;
}e[5000005];
void add(int u,int v,int val)
{
e[++cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
e[cnt].val=val;
}
bool bfs(int s,int t)
{
queue<int> que;
que.push(s);
for (int i=1;i<=n;i++) dis[i]=0,vis[i]=false,cur[i]=head[i];
vis[s]=true;
dis[s]=1;
while (!que.empty())
{
int now=que.front();
que.pop();
for (int i=head[now];i;i=e[i].next)
{
v=e[i].to;
if (!vis[v]&&e[i].val>0)
{
dis[v]=dis[now]+1;
vis[v]=true;
if (v==t) return true;
que.push(v);
}
}
}
return false;
}
int dfs(int now,int t,int flow)
{
if (!flow||now==t) return flow;
int used=0;
for (int i=cur[now];i;i=e[i].next)
{
cur[now]=i;//当前弧优化
v=e[i].to;
if (dis[now]+1!=dis[v]) continue;
int tmp=dfs(v,t,min(flow-used,e[i].val));
if (tmp)
{
e[i].val-=tmp;
e[i^1].val+=tmp;
used+=tmp;
if (flow-used==0) return flow;
}
}
return used;
}
void Dinic(int s,int t)
{
while (bfs(s,t)) ans+=dfs(s,t,0x7fffffff);
}
int main()
{
int s,t,w;
scanf("%d%d%d%d",&n,&m,&s,&t);
cnt=1;
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,0);
}
Dinic(s,t);
printf("%d",ans);
return 0;
}
【网络流相关】最大流的Dinic算法实现的更多相关文章
- 网络流入门—用于最大流的Dinic算法
"网络流博大精深"-sideman语 一个基本的网络流问题 最早知道网络流的内容便是最大流问题,最大流问题很好理解: 解释一定要通俗! 如右图所示,有一个管道系统,节点{1,2,3 ...
- 【最大流之Dinic算法】POJ1273 【 & 当前弧优化 & 】
总评一句:Dinic算法的基本思想比较好理解,就是它的当前弧优化的思想,网上的资料也不多,所以对于当前弧的优化,我还是费了很大的功夫的,现在也一知半解,索性就写一篇博客,来发现自己哪里的算法思想还没理 ...
- 浅谈最大流的Dinic算法
PART 1 什么是网络流 网络流(network-flows)是一种类比水流的解决问题方法,与线性规划密切相关.网络流的理论和应用在不断发展,出现了具有增益的流.多终端流.多商品流以及网络流的分解与 ...
- HDU1532最大流 Edmonds-Karp,Dinic算法 模板
Drainage Ditches Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...
- POJ 1459 Power Network(网络最大流,dinic算法模板题)
题意:给出n,np,nc,m,n为节点数,np为发电站数,nc为用电厂数,m为边的个数. 接下来给出m个数据(u,v)z,表示w(u,v)允许传输的最大电力为z:np个数据(u)z,表示发电 ...
- [模板] 网络流相关/最大流ISAP/费用流zkw
最大流/ISAP 话说ISAP是真快...(大多数情况)吊打dinic,而且还好写... 大概思路就是: 在dinic的基础上, 动态修改层数, 如果终点层数 \(>\) 点数, break. ...
- 最大流:Dinic算法
蒟蒻居然今天第一次写网络流 我太弱啦! 最大流问题有很多解法 虽然isap常数巨小 但是连dinic都写挂的本蒟蒻并不会orz 那么我们选用比较好实现的dinic来解决最大流问题 来一段定义: ...
- POJ 1459 Power Network / HIT 1228 Power Network / UVAlive 2760 Power Network / ZOJ 1734 Power Network / FZU 1161 (网络流,最大流)
POJ 1459 Power Network / HIT 1228 Power Network / UVAlive 2760 Power Network / ZOJ 1734 Power Networ ...
- 网络流最大流——dinic算法
前言 网络流问题是一个很深奥的问题,对应也有许多很优秀的算法.但是本文只会讲述dinic算法 最近写了好多网络流的题目,想想看还是写一篇来总结一下网络流和dinic算法以免以后自己忘了... 网络流问 ...
随机推荐
- 用python实现你的绘画梦想
导语: 你是否还在为当时年少时没有选择自己的梦想而伤心,是否还在为自己的无法成为绘画名家而苦恼,这一切都不需要担心.python都能帮你实现,诶!python怎么能画画呢,一些简单的图案没问题,但 ...
- 一文教您如何通过 Java 压缩文件,打包一个 tar.gz Filebeat 采集器包
欢迎关注笔者的公众号: 小哈学Java, 专注于推送 Java 领域优质干货文章!! 个人网站: https://www.exception.site/essay/create-tar-gz-by-j ...
- UiPath之文件操作
今天给大家介绍一下,在UiPath中如何操作文件,比如需要在某个文件夹中自动创建一个当天日期的文本. 主要使用的activity有: l Assign l Path Exists l If l ...
- 双十一还在盖楼?少年你应该掌握Docker 部署 Consul了
▶ Spring Boot 依赖与配置 Maven 依赖 <dependencyManagement> <dependencies> <dependency> &l ...
- @resource和@autowired的区别是什么-CSDN论坛-CSDN.NET-中国最大的IT技术社区 - Google Chrome
@Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了.@Resource有两个属性是比较重要的,分 ...
- SD-WAN 本地策略与中心策略配置(三)
目录 1. Localized Policy配置 2. Centralized Policy配置 3. Application Route and Traffice Policy 1. Localiz ...
- Class文件结构全面解析(上)
什么是Class文件? 在Java刚刚诞生的时候就提出了一个非常著名的口号:"一次编写,到处运行.(Write Once,Run Anywhere)".为了实现平台无关性,各种不同 ...
- Linux(ubuntu)下切换root用户
输入命令su root切换用户,会提示输入root密码,如果不记得或者是没设置过,那么可以输入sudo passwd root来设置密码,会让你输入两次密码确认.输入完即可使用su root命令切换r ...
- 比较一下inner join(可直接简写为join)和where直接关联
SELECT * FROM A ,B WHERE A.ID = B.ID 是比较常用的2个表关联.之前一直用这个,后来换了家公司发现这家公司的报表大多数都是用inner join,稍微研究了一下.查阅 ...
- java编程思想第四版第十章习题
第一题 package net.mindview.innerclasses; public class Outer { class Inner { Inner(){ System.out.printl ...