最大流模板(EK,Dinic
一、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的更多相关文章
- 图论算法-网络最大流【EK;Dinic】
图论算法-网络最大流模板[EK;Dinic] EK模板 每次找出增广后残量网络中的最小残量增加流量 const int inf=1e9; int n,m,s,t; struct node{int v, ...
- 【Luogu】P3376网络最大流模板(Dinic)
最大流模板成为另一个被攻克的模板题. 今天QDC给我讲了一下Dinic,感觉很好懂.于是为了巩固就把这道题A掉了. 核心思想就是不断BFS分层,然后不断DFS找增广路.找不到之后就可以把答案累加输出了 ...
- 「模板」网络最大流 FF && EK && Dinic && SAP && ISAP
话不多说上代码. Ford-Fulkerson(FF) #include <algorithm> #include <climits> #include <cstdio& ...
- 算法学习笔记(8.1): 网络最大流算法 EK, Dinic, ISAP
网络最大流 目录 网络最大流 EK 增广路算法 Dinic ISAP 作者有话说 前置知识以及更多芝士参考下述链接 网络流合集链接:网络流 最大流,值得是在不超过管道(边)容量的情况下从源点到汇点最多 ...
- 【模板】最大流模板(dinic)
题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行 ...
- P3376 网络最大流模板(Dinic + dfs多路增广优化 + 炸点优化 + 当前弧优化)
### P3376 题目链接 ### 这里讲一下三种优化的实现以及正确性. 1.dfs多路增广优化 一般的Dinic算法中是这样的,bfs() 用于标记多条增广路,以至于能一次 bfs() 出多次 d ...
- 【模板】网络流-最大流模板(Dinic)
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> u ...
- 图论算法-最小费用最大流模板【EK;Dinic】
图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...
- 最大流的EK算法模板
模板题:洛谷p3376 题目大意: 给出一个网络图,以及其源点和汇点,求出其网络最大流. 基本思路: 套模板 EK的时间复杂度O(V*E^2) EK算法思路: 1.通过BFS拓展合法节点(每个节点在本 ...
- P3376 【模板】网络最大流( Edmonds-krap、Dinic、ISAP 算法)
P3376 [模板]网络最大流( Edmonds-krap.Dinic.ISAP 算法) 题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入格式 第一行包含四个正整数N.M.S ...
随机推荐
- php7.3的安装以及在Apache中部署php
安装 php7.3 1.进入php官网:https://www.php.net/downloads.php 2.点击 Windows downloads 3.下载压缩包 4.将下载好的压缩包解压,可选 ...
- 记录一次排查log4cxx库按照日期回滚,不创建新目录的BUG
目录 1.背景 2.排查步骤 2.1.错误代码定位 2.2.问题猜测 2.3.错误代码分析 2.4.错误原因 3.解决方法 1.背景 C++ 项目,使用了 log4cxx 日志库,版本为:0.10.0 ...
- 1月12日内容总结——文件和文件索引、链接、系统时间、克隆、定时任务、paramiko模块、公钥私钥、paramiko代码封装
目录 一.文件相关信息 二.文件索引信息 三.链接信息 四.系统时间 五.机器克隆 六.定时任务 七.paramiko模块 八.公钥私钥 九.paramiko其他操作 十.代码封装 十一.面试题回忆 ...
- drf-视图集、路由系统、action装饰器
1.9个视图扩展类 1.两个视图基类:APIView.GenricAPIView 2.5个视图扩展类:CreateModelMixin,UpdateModelMixin,RetrieveModelMi ...
- javaWeb03-请求转发和请求重定向【包含浏览器与响应编码格式不一致的解决方法】
本文主要讲述javaWeb的请求转发和请求重定向的区别 一. 请求转发 1. 图解 2. 代码示例 Servlet1的代码示例如下 public class Servlet1 extends Http ...
- idea debug---启动超级慢,提示”Method breakpoints may dramatically slow down debugging“的解决办法
https://blog.csdn.net/hanqing456/article/details/111878982 1.问题项目正常启动的时候没问题,debug模式就卡住了,很久不动.我推测是哪个断 ...
- MongoDB数据库记录
启动 MongoDB 服务 标准 URI 连接语法: mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:po ...
- The Missing Semester - 第二讲 学习笔记
第二讲 Shell 工具和脚本 课程视频地址: https://www.bilibili.com/video/BV1Vv411v7FR 本机学习使用平台:虚拟机ubuntu18.04.6 主题一:Sh ...
- 解密Prompt系列2. 冻结Prompt微调LM: T5 & PET & LM-BFF
这一章我们介绍固定prompt微调LM的相关模型,他们的特点都是针对不同的下游任务设计不同的prompt模板,在微调过程中固定模板对预训练模型进行微调.以下按时间顺序介绍,支持任意NLP任务的T5,针 ...
- 达标式减量策略又一例证(STRASS研究)
标签: 类风湿关节炎; T2T策略; TNF抑制剂; 药物减停; STRASS研究 达标式减量策略又一例证(STRASS研究): RA维持期个体化减停TNF拮抗剂是可能的 电邮发布日期: 2016年1 ...