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;
}

还是模板

最新文章

  1. 用unity4.3发布WINDOWS STORE APP应用的方法
  2. Java中的字符串常量池
  3. opencv 手势识别
  4. XCode帮助文档离线下载解决办法
  5. Windows.document对象
  6. Unity Layout碰撞检测
  7. android-包签名
  8. Java多线程中join方法详解
  9. 201521123087 《Java程序设计》第3周学习总结
  10. 利用spring,实现package下的类扫描
  11. android企业级商城源码、360&#176;全景图VR源码、全民直播源码等
  12. javascript之内置函数
  13. centos修改时区并同步时间
  14. Linux下常见音频格式之间的转换方法
  15. 【基础】selenium中元素定位的常用方法(三)
  16. python读取grib grib2气象数据
  17. FastDFS简单入门小demo
  18. canvas合成和裁剪
  19. flink 根据时间消费kafka
  20. 自己封装的ASP.NET的MYSQL的数据库操作类

热门文章

  1. springmvc——mvc:annotation-driven标签的作用
  2. pytest初始化与清除fixture(二)
  3. 权限管理(基本权限、附加权限、ACL权限)
  4. UF_LAYER 图层操作
  5. C++ folly库解读(三)Synchronized —— 比std::lock_guard/std::unique_lock更易用、功能更强大的同步机制
  6. 「Spring Boot架构」集成Mybatis-Plus的实例详解
  7. PyCharm 2020.1 激活教程
  8. DRF之权限和频率限制
  9. Linux之 du的用法
  10. mongodb,redis,mysql的区别和具体应用场景(转)