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. Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://dubbo.apache.org/schema/dubbo]

    dubbo的官方文档写的真好, http://dubbo.apache.org/zh-cn/docs/2.7/user/dependencies/ 在使用dubbo过程中的问题, 和解决 org.sp ...

  2. JUC 并发编程--11, AQS源码原理解析, ReentrantLock 源码解读

    这里引用别人博客,不重复造轮子 https://blog.csdn.net/u012881584/article/details/105886486 https://www.cnblogs.com/w ...

  3. python operator操作符函数

    本模块主要包括一些Python内部操作符对应的函数.这些函数主要分为几类:对象比较.逻辑比较.算术运算和序列操作.

  4. 基于Android平台的图书管理系统的制作(4)

    讲解完学生.职员.书籍这些基础层之后,我们可以来了解一些应用层的活动. 新书上架.借阅排行.黑名单.图书馆介绍.图书馆新闻. 新书上架是查询数据库里的Book表,将最近注册的五本书的基本信息(若图书馆 ...

  5. canal+mysql+kafka实时数据同步安装、配置

    canal+mysql+kafka安装配置 概述 简介 canal译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费. 基于日志增量订阅和消费的业务包括 数 ...

  6. Unity3D学习笔记1——绘制一个三角形

    目录 1. 绪论 2. 概述 3. 详论 3.1. 准备 3.2. 实现 3.3. 解析 3.3.1. 场景树对象 3.3.2. 绘制方法 4. 结果 1. 绪论 最近想学习一下Unity3d,无奈发 ...

  7. react 的优点

    1. 声明式开发 react 是声明式的开发方式,与之对应的是命令式开发方式.之前用jquery写代码的时候,我们都是直接操作dom,这种我们称为命令式的编程.命令式编程需要我们一点点的告诉dom,它 ...

  8. 海康威视摄像头入侵+fofa(CVE-2017-7921)

    海康威视摄像头入侵+fofa(CVE-2017-7921) By:Jesse 重保期间实在是太无聊,于是就找了个海康威视的摄像头日日玩,结果一玩就是一天呢哈哈哈. 1.漏洞编号 CVE-2017-79 ...

  9. rsync 基本使用

    基本参数 # rsync -P test.tar.gz ./ test.tar.gz 395,706,368 48% 377.34MB/s 0:00:01 Or # rsync -avPh test. ...

  10. 4、mysql登录密码修改和找回

    操作适合5.1-5.5:当前的环境是5.5的环境: 4.1.mysql启动的原理: mysqld_safe -> my.cnf ->mysql.sock http://blog.51cto ...