1. 初始化flow(最大流量)为INF(极大值),建边(正向弧和反向弧)
  2. bfs寻找增广路看看有没有路,顺便进行深度标号。如果没有路直接结束输出flow。
  3. 如果有,我们按照深度dfs。dfs时注意在给正向弧减权时给反向弧加权。
  4. ans+=flow,重复2到4步骤,直到无路可走。
  5. 输出结束~

以上就是网络流全部内容(误

概念什么的就不讲啦~

下面来仔细分析板子代码。

  • 初始化ans=0,构建边
  • dinic中心:
while(BFS()) ans+=DFS(start,INF);
  • BFS:
inline bool BFS()
{
memset(dep,-1,sizeof dep);
//每次BFS更新深度,-1代表未被更新或者无路径访问
dep[s]=0;
//起点的深度为0
q.push(s);
while(!q.empty())
{
int u=q.front();q.pop();
for(R int i=head[u];i;i=e[i].nxt)
if(e[i].dis and dep[e[i].to]==-1)//一定有流并且未被访问
dep[e[i].to]=dep[u]+1,q.push(e[i].to);
}
if(dep[end]==-1)return 0;//如果end的深度为-1,无路径到达,此时最大流
return 1;
}
  • DFS
ll DFS(int x,ll flow)
{
if(x==end) return flow;//到终点就返回流
ll used=0;//优化,记录已用过的流
for(R int i=head[x];i;i=e[i].nxt)
{
int u=e[i].to;
if(e[i].dis and dep[u]==dep[x]+1)
{
long long w=DFS(u,min(e[i].dis,flow-used));//求出最大流
used+=w;
e[i].dis-=w;e[i^1].dis+=w;//i^1为相反方向的边,对应加权
if(used==flow)return flow;
}
}
if(!used)dep[x]=-1;//无流可走,说明此点已经无意义了
return used;//最大流
}

P3376 【模板】网络最大流

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define R register
#define INF 1<<30
using namespace std;
template <typename T>
inline T read()
{
T x=0;int w=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
namespace ysr
{
typedef long long ll;
const int maxn=100000;
struct Edge{
int to,nxt;
ll dis;
}e[200000];
int cur[maxn],head[maxn],ecnt=1;//这里记为-1的原因时便于访问正向弧和反向弧
int n,m,s,end,dep[maxn];
inline void addedge(int from,int to,ll dis){
e[++ecnt].to=to,e[ecnt].nxt=head[from],e[ecnt].dis=dis,head[from]=ecnt;
}
inline void add(int from,int to,ll dis){
addedge(from,to,dis);addedge(to,from,0);
}
ll DFS(int x,ll flow)
{
if(x==end) return flow;
ll used=0;
for(R int i=head[x];i;i=e[i].nxt)
{
int u=e[i].to;
if(e[i].dis and dep[u]==dep[x]+1)
{
long long w=DFS(u,min(e[i].dis,flow-used));
used+=w;
e[i].dis-=w;e[i^1].dis+=w;
if(used==flow)return flow;
}
}
if(!used)dep[x]=-1;
return used;
}
queue<int>q;
inline bool BFS()
{
memset(dep,-1,sizeof dep);
dep[s]=0;
q.push(s);
while(!q.empty())
{
int u=q.front();q.pop();
for(R int i=head[u];i;i=e[i].nxt)
if(e[i].dis and dep[e[i].to]==-1)
dep[e[i].to]=dep[u]+1,q.push(e[i].to);
}
if(dep[end]==-1)return 0;
return 1;
}
inline void work()
{
n=read<int>(),m=read<int>(),s=read<int>(),end=read<int>();
ll ans=0;
int a,b;
ll c;
for(R int i=0;i<m;i++)a=read<int>(),b=read<int>(),c=read<ll>(),add(a,b,c);
while(BFS())
ans+=DFS(s,INF);
printf("%lld\n",ans);
}
}
signed main()
{
ysr::work();
return 0;
}

大家一定已经发现我定义了一个cur数组不知道但什么的。这其实就是【当前弧优化】的数组,虽然我在上面没有使用。

这也不是什么高深的玩意。我们证明,如果一个点在之前的dfs中已经把一些边考虑过了,由于在当前和以后的流的dfs中这些边都是增广过的,也就是再也没法做出贡献了,那么我们用一个数组cur记录一下考虑到哪里了然后下一侧dfs时接着上次的就行了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define R register
#define INF 1<<30
using namespace std;
template <typename T>
inline T read()
{
T x=0;int w=0;char c=getchar();
while(!isdigit(c))w|=c=='-',c=getchar();
while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
return w?-x:x;
}
namespace ysr
{
typedef long long ll;
const int maxn=100000;
struct Edge{
int to,nxt;
ll dis;
}e[200000];
int cur[maxn],head[maxn],ecnt=1;//这里记为-1的原因时便于访问正向弧和反向弧
int n,m,s,end,dep[maxn];
inline void addedge(int from,int to,ll dis){
e[++ecnt].to=to,e[ecnt].nxt=head[from],e[ecnt].dis=dis,head[from]=ecnt;
}
inline void add(int from,int to,ll dis){
addedge(from,to,dis);addedge(to,from,0);
}
ll DFS(int x,ll flow)
{
if(x==end) return flow;
ll used=0;
for(R int i=cur[x];i;i=e[i].nxt)
{
cur[x]=i;
int u=e[i].to;
if(e[i].dis and dep[u]==dep[x]+1)
{
long long w=DFS(u,min(e[i].dis,flow-used));
used+=w;
e[i].dis-=w;e[i^1].dis+=w;
if(used==flow)return flow;
}
}
if(!used)dep[x]=-1;
return used;
}
queue<int>q;
inline bool BFS()
{
for(R int i=0;i<=n;i++)cur[i]=head[i],dep[i]=-1;
dep[s]=0;
q.push(s);
while(!q.empty())
{
int u=q.front();q.pop();
for(R int i=head[u];i;i=e[i].nxt)
if(e[i].dis and dep[e[i].to]==-1)
dep[e[i].to]=dep[u]+1,q.push(e[i].to);
}
if(dep[end]==-1)return 0;
return 1;
}
inline void work()
{
n=read<int>(),m=read<int>(),s=read<int>(),end=read<int>();
ll ans=0;
int a,b;
ll c;
for(R int i=0;i<m;i++)a=read<int>(),b=read<int>(),c=read<ll>(),add(a,b,c);
while(BFS())
ans+=DFS(s,INF);
printf("%lld\n",ans);
}
}
signed main()
{
ysr::work();
return 0;
}

还是模板

最大网络流dinic的更多相关文章

  1. POJ 1273 Drainage Ditches (网络流Dinic模板)

    Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover ...

  2. ACM/ICPC 之 有流量上下界的网络流-Dinic(可做模板)(POJ2396)

    //有流量上下界的网络流 //Time:47Ms Memory:1788K #include<iostream> #include<cstring> #include<c ...

  3. 网络流Dinic(本篇介绍最大流)

    前言:看到网上Dinic和ISAP的比较,多数人认为ISAP更快,不容易爆栈.当然,也有少数人认为,在多数情况下,Dinic比较稳定.我认为Dinic的思路比ISAP更简明,所以选择了Dinc算法 介 ...

  4. 模板——网络流Dinic

    感谢这位大佬的博客:https://www.cnblogs.com/SYCstudio/p/7260613.html 给予了我莫大的帮助! 主要说一下网络流的几个注意点: 1.和二分图匹配相似,无法继 ...

  5. 网络流dinic实现总结

    太羞耻了,搞了半天居然没发现自己写的不是dinic,直到被一道时限紧的题目卡掉才发现 int dfs(int now,int flow,int sum) { if(now==n) return flo ...

  6. poj 1459 Power Network : 最大网络流 dinic算法实现

    点击打开链接 Power Network Time Limit: 2000MS   Memory Limit: 32768K Total Submissions: 20903   Accepted:  ...

  7. POJ 1273 Drainage Ditches(网络流dinic算法模板)

    POJ 1273给出M条边,N个点,求源点1到汇点N的最大流量. 本文主要就是附上dinic的模板,供以后参考. #include <iostream> #include <stdi ...

  8. 高效的网络流dinic算法模版

    #include <cstring> #include <algorithm> #include <vector> #define Maxn 120010 #def ...

  9. 网络流(dinic算法)

    网络最大流(dinic) 模型 在一张图中,给定一个源点s,给定汇点t,点之间有一些水管,每条水管有一个容量,经过此水管的水流最大不超过容量,问最大能有多少水从s流到t(s有无限多的水). 解法 di ...

随机推荐

  1. 深入理解java虚拟机笔记Chapter3-垃圾收集器

    垃圾收集器 垃圾收集(Garbage Collection,GC),它的任务是解决以下 3 件问题: 哪些内存需要回收? 什么时候回收? 如何回收? 本节补充知识: ① s:Survivor区 新生代 ...

  2. 十五、.net core(.NET 6)搭建RabbitMQ消息队列生产者和消费者的简单方法

    搭建RabbitMQ简单通用的直连方法 如果还没有MQ环境,可以参考上一篇的博客,在windows系统上的rabbitmq环境搭建.如果使用docker环境,可以直接百度一下,应该就一个语句就可以搞定 ...

  3. 数据结构与算法Python版 熟悉哈希表,了解Python字典底层实现

    Hash Table 散列表(hash table)也被称为哈希表,它是一种根据键(key)来存储值(value)的特殊线性结构. 常用于迅速的无序单点查找,其查找速度可达到常数级别的O(1). 散列 ...

  4. SpringBoot线程池的创建、@Async配置步骤及注意事项

    最近在做订单模块,用户购买服务类产品之后,需要进行预约,预约成功之后分别给商家和用户发送提醒短信.考虑发短信耗时的情况所以我想用异步的方法去执行,于是就在网上看见了Spring的@Async了. 但是 ...

  5. docker入门详解

    这可能是最为详细的Docker总结 Docker是什么? 在计算机技术日新月异的今天, Docker 在国内发展的如火如荼,特别是在一线互联网公司, Docker 的使用是十分普遍的,甚至成为了一些企 ...

  6. 入门Kubernetes - YAML文件

    前言 前篇文章中简单了解到如何把.Net Core 程序部署到k8s中,过程中使用了多个*.yaml文件,那么这些文件的格式及含义.语法是如何的呢? 接下来,进一步了解学习 一.YAML介绍: 1.简 ...

  7. Kubernetes ConfigMap详解,多种方式创建、多种方式使用

    我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 简介 配置是程序绕不开的话题,在Kubernetes中使用ConfigMap来配置,它本质其实就是键值对.本文讲解如何 ...

  8. R语言--图形基本使用1

    1 使用图形 1.1 交互式绘图 使用的是内置数据集:mtcars 画出散点图:plot(mtcars$mpg,mtcars$wt) 给图形加标题:title("车辆耗油与重量之间的关系&q ...

  9. Spring Boot Docker

    1.  IDEA中配置Docker Docker默认只接受本地客户端的请求,为了能够远程访问它,首先要开放Docker的监听端口,运行外部应用可以访问 修改 /lib/systemd/system/d ...

  10. Python如何设计面向对象的类(上)

    Python是一门高级语言,支持面向对象设计,如何设计一个符合Python风格的面向对象的类,是一个比较复杂的问题,本文提供一个参考,表达一种思路,探究一层原理. 目标 期望实现的类具有以下基本行为: ...