Dinic算法求最大流
题目
【模板】网络最大流
题目描述
如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。
输入格式
第一行包含四个正整数 ,分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来 行每行包含三个正整数 ,表示第 条有向边从 出发,到达 ,边权为 (即该边最大流量为 )。
输出格式
一行,包含一个正整数,即为该网络的最大流。
样例 #1
样例输入 #1
4 5 4 3 4 2 30 4 3 20 2 3 20 2 1 30 1 3 40
样例输出 #1
50
提示
样例输入输出 1 解释
题目中存在 条路径:
- ,该路线可通过 的流量。
- ,可通过 的流量。
- ,可通过 的流量(边 之前已经耗费了 的流量)。
故流量总计 。输出 。
数据规模与约定
- 对于 的数据,保证 ,。
- 对于 的数据,保证 ,,。
代码
// Problem: P3376 【模板】网络最大流 // Contest: Luogu // URL: https://www.luogu.com.cn/problem/P3376 // Memory Limit: 128 MB // Time Limit: 2000 ms // // Powered by CP Editor (https://cpeditor.org) //fw #include<bits/stdc++.h> #define zp ios::sync_with_stdio(false);cin.tie(0); cout.tie(0); #define pii pair <int, int> #define pll pair <ll, ll> #define endl '\n' #define il inline #define pb push_back #define fi first #define se second #define lc u<<1 #define rc u<<1|1 using namespace std; typedef long long ll; const int INF=0x3f3f3f3f; const int N=10010,M=200010; int n,m,S,T;//定义点数、边数、源点、汇点 ll h[N],e[M],ne[M],f[M],idx;//前向星+容量 ll q[N],d[N],cur[N];//宽搜队列、分层图层数、当前弧 void add(int a,int b,int c) { e[idx]=b,f[idx]=c,ne[idx]=h[a],h[a]=idx++;//正向边初始容量 e[idx]=a,f[idx]=0,ne[idx]=h[b],h[b]=idx++;//退流管道初始流量为0 } bool bfs() { int hh=0,tt=0; memset(d,-1,sizeof d); q[0]=S,d[S]=0;//宽搜以及分层图的初始化 cur[S]=h[S];//记录当前弧初始状态 while(hh<=tt) { int t=q[hh++]; for(int i=h[t];~i;i=ne[i]) { int ver=e[i]; if(d[ver]==-1&&f[i])//如果没有记录层数并且容量不为0 { d[ver]=d[t]+1;//记录层数 cur[ver]=h[ver];//初始化节点的当前弧 if(ver==T)return true;//到达汇点则存在增广路 q[++tt]=ver;//将当前点入队 } } } return false;//找不到增广路 } ll find(int u,int limit) { if(u==T)return limit;//到达汇点直接返回流量 ll flow=0;//累加从当前点流出去的可行流 for(int i=cur[u];~i&&flow<limit;i=ne[i])//从当前弧开始遍历 { cur[u]=i;//当前弧优化,记录已经用到了哪一个点,防止重复搜索已经被榨干的边 ll ver=e[i]; if(d[ver]==d[u]+1&&f[i])//使用分层找到最短的一条增广路,优化搜索顺寻 { ll t=find(ver,min(f[i],limit-flow));//获得从当前点流出去的可行流, //下一层的流量值不能超过下一条边的容量和上一层的剩余容量 if(!t)d[ver]=-1;//残枝优化,如果当前点已经没有可行流则把当前点踢出分层图 f[i]-=t,f[i^1]+=t,flow+=t;//正向边可用流量减少,反向边可用流量增加,累加可行流 } } return flow;//返回最大可行流 } ll dinic() { ll r = 0, flow;//定义最大可行流r和当前搜索得到的流量flow while (bfs()) //如果bfs能找到增广路 while (flow = find(S, INF)) //当在这张分层图上仍然能找到可行流时 r += flow;//累加可行流 return r;//返回最大可行流 } int main() { cin>>n>>m>>S>>T; memset(h,-1,sizeof h); while(m--) { int a,b,c; cin>>a>>b>>c;//输入正向的点和容量 add(a,b,c);//建立正向边和退流管道 } cout<<dinic()<<endl; return 0; }
学习资料
362 网络流 最大流 Dinic 算法_哔哩哔哩_bilibili
AcWing 2172. Dinic_ISAP求最大流 - AcWing
一个菜鸡
本文作者:Avarice_Zhao
本文链接:https://www.cnblogs.com/avarice/p/16450506.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步