一、EK

EK算法:用bfs找增广路直到找不到为止。找到则更新最大流和残余网络,找不到则结束。

残余网络:对于一条走过的边,其正向边权值减少相应值,反向边权值增加相应值(用于反悔)。

增广路:从所求起点到终点之间还可以增大流量的路径。

复杂度O(n*m^2)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,m,s,t;
const int maxn=220;
ll G[maxn][maxn],flow[maxn],pre[maxn];//flow:源点到当前点的流量,pre增广路的上一条边
ll bfs(int s,int t){//找增广路
queue<int>qu;
while(!qu.empty())qu.pop();
memset(pre,-1,sizeof pre);//记录前驱
pre[s]=0;
flow[s]=0x3f3f3f3f;
qu.push(s);
while(!qu.empty()){
int p=qu.front();qu.pop();
if(p==t)break;
for(int i=1;i<=n;i++){
if(i!=s&&G[p][i]>0&&pre[i]==-1){
pre[i]=p;
flow[i]=min(flow[p],G[p][i]);//选承载量最小的
qu.push(i);
}
}
}
if(pre[t]==-1)return -1;
return flow[t];
}
ll EK(int s,int t){
ll ans=0,tot=0;
while(1){
ans=bfs(s,t);
if(ans==-1)break;
int p=t;
while(p!=s){//回溯整条增广路,进行更新
G[pre[p]][p]-=ans;
G[p][pre[p]]+=ans;//反向边
p=pre[p];
}
tot+=ans;
}
return tot;
}
int main()
{
int i,j;
cin>>n>>m>>s>>t;
memset(G,0,sizeof G);
memset(flow,0,sizeof flow);
for(i=0;i<m;i++){
int a,b;ll c;cin>>a>>b>>c;
G[a][b]+=c;//累计容量 防止重边
}
cout<<EK(s,t);
return 0;
}

 二、Dinic

有时候EK会超时 因为可能会出现增广路经过的其中一条边值为1,而其他边值很大的情况,则需要一直增广。

而Dinic利用分层可以一次dfs实现多次增广,从而优化EK算法。

Dinic算法:先利用bfs进行分层(只能往层数+1的地方走),再利用dfs实现进行增广(一次dfs实现多次增广)。该步骤一直循环直到不可分层为止。

复杂度O(m*n^2)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 50005;
const int maxm=500010;//边
const int inf =0x3f3f3f3f;
int head[maxn],dis[maxn];
struct Edge
{
int to,next,f;
}edge[maxm]; //链式前向星
int s,t,cnt;
void add(int u,int v,int f)
{
edge[cnt].to=v;
edge[cnt].f=f;
edge[cnt].next=head[u];
head[u]=cnt++; //正向建边//相邻边则为反向边,cnt从0开始(1不行)
edge[cnt].to=u;
edge[cnt].f=0;
edge[cnt].next=head[v];
head[v]=cnt++; //反向建边
}
bool bfs()
{
memset(dis,-1,sizeof(dis));
queue <int> que;
dis[s]=0;
que.push(s);
while(!que.empty())
{
int u=que.front();
que.pop();
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
int f=edge[i].f;
if(dis[v]==-1&&f>0)//有流量且未访问过
{
dis[v]=dis[u]+1;//分层
if(v==t) return true;
que.push(v);
}
}
}
return false;
}
int dfs(int x,int maxf) //maxf表多少流量流到当前节点
{
if(x==t||maxf==0) return maxf;
int flow=0;
for(int i=head[x];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
int f=edge[i].f;
if(dis[v]==dis[x]+1&&f>0)
{
f=dfs(v,min(f,maxf-flow));//当前边的容量和该点剩余量取min
edge[i].f-=f;
edge[i^1].f+=f;//相邻边则为反向边,通过异或可以直接找到反向边
flow+=f;
if(flow==maxf) return flow;
}
}
return flow;
}
int main()
{
int T,n,m,k;
cin>>n>>m>>s>>t;
cnt=0;
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++)
{
int u,v,f;
scanf("%d%d%d",&u,&v,&f);
add(u,v,f); //加边
}
int ans=0;
while(bfs()) ans+=dfs(s,inf);
cout<<ans<<endl;
}

经过bfs分层后有123三层,从s出发,只会往第二层的三个点依次进行dfs。dfs手动模拟即可理解,每次走过时记得更新残余网络。

最大流模板(EK,Dinic的更多相关文章

  1. 图论算法-网络最大流【EK;Dinic】

    图论算法-网络最大流模板[EK;Dinic] EK模板 每次找出增广后残量网络中的最小残量增加流量 const int inf=1e9; int n,m,s,t; struct node{int v, ...

  2. 【Luogu】P3376网络最大流模板(Dinic)

    最大流模板成为另一个被攻克的模板题. 今天QDC给我讲了一下Dinic,感觉很好懂.于是为了巩固就把这道题A掉了. 核心思想就是不断BFS分层,然后不断DFS找增广路.找不到之后就可以把答案累加输出了 ...

  3. 「模板」网络最大流 FF && EK && Dinic && SAP && ISAP

    话不多说上代码. Ford-Fulkerson(FF) #include <algorithm> #include <climits> #include <cstdio& ...

  4. 算法学习笔记(8.1): 网络最大流算法 EK, Dinic, ISAP

    网络最大流 目录 网络最大流 EK 增广路算法 Dinic ISAP 作者有话说 前置知识以及更多芝士参考下述链接 网络流合集链接:网络流 最大流,值得是在不超过管道(边)容量的情况下从源点到汇点最多 ...

  5. 【模板】最大流模板(dinic)

    题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行 ...

  6. P3376 网络最大流模板(Dinic + dfs多路增广优化 + 炸点优化 + 当前弧优化)

    ### P3376 题目链接 ### 这里讲一下三种优化的实现以及正确性. 1.dfs多路增广优化 一般的Dinic算法中是这样的,bfs() 用于标记多条增广路,以至于能一次 bfs() 出多次 d ...

  7. 【模板】网络流-最大流模板(Dinic)

    #include <cstdio> #include <cstring> #include <algorithm> #include <queue> u ...

  8. 图论算法-最小费用最大流模板【EK;Dinic】

    图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...

  9. 最大流的EK算法模板

    模板题:洛谷p3376 题目大意: 给出一个网络图,以及其源点和汇点,求出其网络最大流. 基本思路: 套模板 EK的时间复杂度O(V*E^2) EK算法思路: 1.通过BFS拓展合法节点(每个节点在本 ...

  10. P3376 【模板】网络最大流( Edmonds-krap、Dinic、ISAP 算法)

    P3376 [模板]网络最大流( Edmonds-krap.Dinic.ISAP 算法) 题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入格式 第一行包含四个正整数N.M.S ...

随机推荐

  1. 读Java8函数式编程笔记01_Lambda表达式

    1. Java 8函数式编程 1.1. 没有单子 1.2. 没有语言层面的惰性求值 1.3. 没有为不可变性提供额外支持 1.4. 集合类可以拥有一些额外的方法:default方法 2. 现实世界中, ...

  2. 【单片机】nRF52832 实现停止蓝牙广播接口

    前言 有一个项目使用了 nRF52832 芯片作为主控,其中有用到蓝牙功能.在对蓝牙接口进一步封装的时候,发现 SDK 居然没有停止广播的接口,咨询了代理 FAE,对方也没有找到关闭广播的接口.后来通 ...

  3. vulnhub靶场渗透实战15-matrix-breakout-2-morpheus

    vulnhub靶场渗透实战15-matrix-breakout-2-morpheus 靶机搭建:vulnhub上是说vbox里更合适.可能有vbox版本兼容问题,我用的vmware导入. 靶场下载地址 ...

  4. MySQL-SQL语法、字段类型

    1.字符编码与配置文件 1.\s:查看当前MySQL相关信息:当前用户.版本.编码.端口号. """ Server characterset.Db characterse ...

  5. Gateway服务网关 (入门到使用)

    Gateway服务网关 Gateway也要作为微服务注册到nacos中 Zuul也是网关但比较老是一种阻塞式编程:Spring Cloud Gateway 是 Spring Cloud 的一个全新项目 ...

  6. 重学SpringBoot. step1 全注解的SpringBoot

    参考:<深入浅出SpringBoot 2.x> 全注解的SpringBoot 用户可以通过注解将所需要的对象,存放到IOC容器中,然后SpringBoot可以根据这些需要使用的情况,自动注 ...

  7. 【TS】函数和函数类型

    在使用函数的时候,通常会给函数传值,或者给函数一个返回值调用,这个时候就会涉及到函数类型. 函数类型分为两个方面: 1.函数参数 2.函数返回值 语法: function 函数名( 参数 : 参数类型 ...

  8. B端业务中仓库标签打印系统设计方案

    需求背景: 仓库在给客户货物打包途中需要在包裹上贴标签,在客户比较多且标签样式多样化的前提下,给仓库人员带来了工作量,为了节约仓库人员工作流程时间,公司开发了一套标签管理系统: 前提条件:选择专属打印 ...

  9. 前端开发工具VsCode官网下载太慢?直接失败?

    我有个朋友来到公司以后,在搭建基本开发环境时,什么nodejs安装包,vscode包等等都是由同事直接分享,然后一键安装,从来没去过官网下载,以至于想更新新版本的时候首次进入官网有点懵逼,相信很多同学 ...

  10. Eureka高可用集群服务端和客户端配置

    微服务应用中,生产环境一般都需要保障服务注册中心的高可用!高可用也分好几个等级,例如:同数据中心(可用Zone区)高可用-->同地域(Region)跨数据中心(可用Zone区)高可用--> ...