Luogu P3376

由于\(EK\)算法求最大流时每一次只求一条增广路,时间复杂度会比较高。尽管实际应用中表现比较优秀,但是有一些题目还是无法通过。

那么我们就会使用\(Dinic\)算法实现多路增广。

算法的基本流程如下:

  1. \(BFS\)对图进行分层,求出终点所在的层数
  2. \(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算法实现的更多相关文章

  1. 网络流入门—用于最大流的Dinic算法

    "网络流博大精深"-sideman语 一个基本的网络流问题 最早知道网络流的内容便是最大流问题,最大流问题很好理解: 解释一定要通俗! 如右图所示,有一个管道系统,节点{1,2,3 ...

  2. 【最大流之Dinic算法】POJ1273 【 & 当前弧优化 & 】

    总评一句:Dinic算法的基本思想比较好理解,就是它的当前弧优化的思想,网上的资料也不多,所以对于当前弧的优化,我还是费了很大的功夫的,现在也一知半解,索性就写一篇博客,来发现自己哪里的算法思想还没理 ...

  3. 浅谈最大流的Dinic算法

    PART 1 什么是网络流 网络流(network-flows)是一种类比水流的解决问题方法,与线性规划密切相关.网络流的理论和应用在不断发展,出现了具有增益的流.多终端流.多商品流以及网络流的分解与 ...

  4. HDU1532最大流 Edmonds-Karp,Dinic算法 模板

    Drainage Ditches Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) To ...

  5. POJ 1459 Power Network(网络最大流,dinic算法模板题)

    题意:给出n,np,nc,m,n为节点数,np为发电站数,nc为用电厂数,m为边的个数.      接下来给出m个数据(u,v)z,表示w(u,v)允许传输的最大电力为z:np个数据(u)z,表示发电 ...

  6. [模板] 网络流相关/最大流ISAP/费用流zkw

    最大流/ISAP 话说ISAP是真快...(大多数情况)吊打dinic,而且还好写... 大概思路就是: 在dinic的基础上, 动态修改层数, 如果终点层数 \(>\) 点数, break. ...

  7. 最大流:Dinic算法

    蒟蒻居然今天第一次写网络流 我太弱啦! 最大流问题有很多解法 虽然isap常数巨小 但是连dinic都写挂的本蒟蒻并不会orz 那么我们选用比较好实现的dinic来解决最大流问题 来一段定义:    ...

  8. 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 ...

  9. 网络流最大流——dinic算法

    前言 网络流问题是一个很深奥的问题,对应也有许多很优秀的算法.但是本文只会讲述dinic算法 最近写了好多网络流的题目,想想看还是写一篇来总结一下网络流和dinic算法以免以后自己忘了... 网络流问 ...

随机推荐

  1. 表格导出到excel的样式消失该如何修改

    工作中遇到一需求,要将后台的表格导出到excel后的表格样式该如何修改呢? 其实表格导出首先需要了解两个插件:jquery.table2excel.js和tableExport.js 1.第一步,写一 ...

  2. Python实现日志文件写入或者打印--类似于Java的Log4j

    开发过Java的应该都知道Log4j的重要性,尤其是在开发测试中,能够让开发和测试人员方便找的bug,Python也有和Log4j相同功能的库那就是logging库,其功能非常强大,在开发测试中很方便 ...

  3. go中的数据结构字典-map

    1. map的使用 golang中的map是一种数据类型,将键与值绑定到一起,底层是用哈希表实现的,可以快速的通过键找到对应的值. 类型表示:map[keyType][valueType] key一定 ...

  4. aop的简单使用(代码和配置记录)

    Spring aop 简单示例 简单的记录一下spring aop的一个示例 基于两种配置方式: 基于xml配置 基于注解配置 这个例子是模拟对数据库的更改操作添加事物 其实并没有添加,只是简单的输出 ...

  5. 爬虫实践--CBA历年比赛数据

    闲来无聊,刚好有个朋友来问爬虫的事情,说起来了CBA这两年的比赛数据,做个分析,再来个大数据啥的.来了兴趣,果然搞起来,下面分享一下爬虫的思路. 1.选取数据源 这里我并不懂CBA,数据源选的是国内某 ...

  6. java编程思想第四版第八章总结

    1. 多态的含义 面向对象的三大基本特征: 封装,继承,多态. 多态是干什么的? 多态将做什么和怎么做分离开.从另一个角度将接口是实现类分离开. 多态的作用 消除类型之间耦合的关系 使用多态的好处? ...

  7. 利用Xshell配置ssh免密码登录虚拟机,进行虚拟机与物理机的传输

    先说一下 Xshell如何无密连接虚拟机: ssh登录提供两种认证方式:口令(密码)认证方式和密钥认证方式.其中口令(密码)认证方式是我们最常用的一种,这里介绍密钥认证方式登录到linux的方法.使用 ...

  8. 在linux (centos)上使用puppeteer实现网页截图

    1.安装nodejs和npm # 下载解压 wget -c https://nodejs.org/dist/v8.9.1/node-v8.9.1-linux-x64.tar.xz tar -xvf n ...

  9. shell中tar加密打包

    tar 打包是一个很常见的操作,但是当打了一个包却又不想让别人看到里面的小秘密的时候就可以使用加密的方法进行打包. 以下是一个脚本实现的加密打包和解密的shell脚本: cat tar_passwor ...

  10. ffmpeg 编译安装

    1.FFmpeg编译 1.1.安装yasm 这里我是直接通过ubuntu包安装的,当然也可以通过编译源码来安装. sudo apt-get install yasm 1.2.下载FFmpeg git ...