题目链接: P3376 【模板】网络最大流

Dinic

Dinic算法是网络流最大流的优化算法之一,每一步对原图进行分层,然后用DFS求增广路。时间复杂度是O(n^2*m),Dinic算法最多被分为n个阶段,每个阶段包括建层次网络和寻找增广路两部分。
Dinic算法的思想是分阶段地在层次网络中增广。它与最短增广路算法不同之处是:最短增广路每个阶段执行完一次BFS增广后,要重新启动BFS从源点Vs开始寻找另一条增广路;而在Dinic算法中,只需一次DFS过程就可以实现多次增广。

层次图:

层次图,就是把原图中的点按照点到源的距离分“层”,只保留不同层之间的边的图。

算法流程:

1、根据残量网络计算层次图。
2、在层次图中使用DFS进行增广直到不存在增广路。
3、重复以上步骤直到无法增广。

实现

首先对每条弧存一条反向弧,初始流量为0,当正向弧剩余流量减少时,反向弧剩余流量随之增加,这样就为每条弧提供了一个反悔的机会,可以让一个流沿反向弧退回而去寻找更优的路线。对于一个网络流图,用bfs将图分层,只保留每个点到下一个层次的弧,目的是减少寻找增广路的代价。对于每一次可行的增广操作,用dfs的方法寻找一条由源点到汇点的路径并获得这条路径的流量c。根据这条路径修改整个图,将所经之处正向边流量减少c,反向边流量增加c。如此反复直到bfs找不到可行的增广路线。

当前弧优化:

对于一个节点x,当它在dfs中走到了第i条弧时,前i-1条弧到汇点的流一定已经被流满而没有可行的路线了。那么当下一次再访问x节点的时候,前i-1条弧就可以被删掉而没有任何意义了。所以我们可以在每次枚举节点x所连的弧时,改变枚举的起点,这样就可以删除起点以前的所有弧以达到优化的效果。

本题增强了数据,时间更是卡到了500ms,以前的好多题解都过不去了。
有一个问题是我使用弧优化最后两个点跑了750ms T 了,但是我把弧优化去掉了以后只跑了60ms,成功AC,真是很玄学。

我知道哪里的问题了,蓝书《算法竞赛进阶指南》上的弧优化好像有点问题,now[x] = i好像应该放到for循环里面,我参照的洛谷日报上的写法,跑了最后一个点只13ms。(哪位大佬能不能告诉我为什么)

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<math.h>
#include<cstring>
#include<queue>
//#define ls (p<<1)
//#define rs (p<<1|1)
#define over(i,s,t) for(register int i = s;i <= t;++i)
#define lver(i,t,s) for(register int i = t;i >= s;--i)
//#define int __int128
//#define lowbit(p) p&(-p)
using namespace std;typedef long long ll;
typedef pair<int,int> PII;
const ll INF = 1e18;
const int N = 5e2+7;
const int M = 2e5+7;int head[N],nex[M],ver[M],tot = 1;
ll edge[M];
int n,m,s,t;
ll maxflow;
ll deep[N];//层级数,其实应该是level
int now[M];//当前弧优化
queue<int>q;inline void read(int &x){int f=0;x=0;char c=getchar();while(c<'0'||c>'9')f|=c=='-',c=getchar();while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();x=f?-x:x;
}inline void add(int x,int y,int z){//建正边和反向边ver[++tot] = y;edge[tot] = z;nex[tot] = head[x];head[x] = tot;ver[++tot] = x;edge[tot] = 0;nex[tot] = head[y];head[y] = tot;
}inline bool bfs(){//在残量网络中构造分层图over(i,1,n)deep[i] = INF;while(!q.empty())q.pop();q.push(s);deep[s] = 0;now[s] = head[s];//一些初始化while(!q.empty()){int x = q.front();q.pop();for(int i = head[x];i;i = nex[i]){int y = ver[i];if(edge[i] > 0 && deep[y] == INF){//没走过且剩余容量大于0q.push(y);now[y] = head[y];//先初始化,暂时都一样deep[y] = deep[x] + 1;if(y == t)return 1;//找到了}}}return 0;
}//flow是整条增广路对最大流的贡献,rest是当前最小剩余容量,用rest去更新flow
ll dfs(int x,ll flow){//在当前分层图上增广if(x == t)return flow;ll ans = 0,k,i;for(i = now[x];i && flow;i = nex[i]){now[x] = i;//当前弧优化(避免重复遍历从x出发的不可拓展的边)int y = ver[i];if(edge[i] > 0 && (deep[y] == deep[x] + 1)){//必须是下一层并且剩余容量大于0k = dfs(y,min(flow,edge[i]));//取最小if(!k)deep[y] = INF;//剪枝,去掉增广完毕的点edge[i] -= k;//回溯时更新edge[i ^ 1] += k;//成对变换ans += k;flow -= k;}//if(!flow)return rest;}return ans;
}void dinic(){while(bfs())maxflow += dfs(s,INF);
}int main()
{read(n);read(m);read(s);read(t);tot = 1;//成对变换over(i,1,m){int x,y,z;read(x);read(y);read(z);add(x,y,z);}dinic();printf("%lld\n",maxflow);return 0;
}

【网络流】解题报告:luogu P3376 【模板】网络最大流相关推荐

  1. 【ybt金牌导航3-2-1】【luogu P3376】网络最大流【Dinic算法】

    网 络 最 大 流 网络最大流 网络最大流 题目链接:ybt金牌导航3-2-1 / luogu P3376 题目 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入 第一行包含四个正整数 ...

  2. [Luogu] P3376 模板-网络流-最大流

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

  3. 【洛谷P3376】网络最大流【网络流】

    分析 网络流算法本身是之前学过的,今天拿出来复习打个板子. 最原始的思路应该是搜索每一条路,每次进行增广的操作,知道不能增广为止.显然,这种思路复杂度比较高. 如何进行优化?就是dinic算法.上面那 ...

  4. Dinic最大流 || Luogu P3376 【模板】网络最大流

    题面:[模板]网络最大流 代码: 1 #include<cstring> 2 #include<cstdio> 3 #include<iostream> 4 #de ...

  5. 解题报告:线性规划与网络流24题

    目录 A.飞行员配对方案问题 (二分图最大匹配)(最大流)[提高+/省选- ] B.太空飞行计划问题(最大权闭合图转最小割.最小割方案输出)[省选/NOI- ] C.最小路径覆盖问题(有向无环图最小路 ...

  6. 经典网络流题目模板(P3376 + P2756 + P3381 : 最大流 + 二分图匹配 + 最小费用最大流)...

    题目来源 P3376 [模板]网络最大流 P2756 飞行员配对方案问题 P3381 [模板]最小费用最大流 最大流 最大流问题是网络流的经典类型之一,用处广泛,个人认为网络流问题最具特点的操作就是建 ...

  7. 洛谷P3376 【模板】网络最大流

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

  8. 【洛谷 - P3376 】【模板】网络最大流

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

  9. 网络流20+4题解题报告(已更前20题)

    链接:网络流20+4题解题报告 代码预览:Github 转载于:https://www.cnblogs.com/water-mi/p/10538858.html

最新文章

  1. 直接插入排序与希尔排序
  2. 使用Java 8 Optional避免空指针异常
  3. UITextView 取消键盘方法
  4. C++面试常见问题整理汇总(面试者必看哦!)
  5. Something about Giraffe (II)
  6. 神经网络模型遇到瓶颈?这些Tricks让你相见恨晚!
  7. Android开发:Handler Runnable和Thread之间的区别和联系 应用--------------------看完本篇,从此一览无余!...
  8. PAT---数字分类
  9. SpringBoot在前端发送url时,不能识别特殊字符的问题
  10. FISCO BCOS 《新摩登时代》:卓别林演绎共识与同步流程优化
  11. jar 文件不能运行
  12. 酷比魔方iwork8刷机shell_酷比魔方iwork8超级版双系统刷机教程,remix+Windows10,序列号i1开头数字结尾...
  13. python 爬取网易云音乐歌单
  14. 看Panasonic EZ0l21充电器有感
  15. 在兼容系统上升级DELL SATA硬盘的固件
  16. MX6Q WM8978 KSZ8863调试笔记
  17. Python文件操作-替换srt文件行文本
  18. Scratch(二十六):小兔子乖乖
  19. 想做个可以打印的服务,想用printdocument,但是不用winform,有谁知道怎么实现吗?万分感谢!
  20. Python cmd库的使用

热门文章

  1. pytorch2——Pytorch基础数据结构——张量(深度之眼)
  2. python selenium - web自动化环境搭建
  3. SpringCloud(第 002 篇)简单电影微服务类(消费方,而提供方为用户微服务)
  4. 看初中生如何高薪就业
  5. Backbone的写类方式
  6. 2010年7月blog汇总:OpenTest、MetaModelEngine和敏捷个人
  7. java链式编程_Java 中的链式编程
  8. 用在数据科学上的 Python:你可能忘记的 8 个概念
  9. go kegg_3分钟了解GO/KEGG功能富集分析
  10. linux命令的使用实验报告,Linux实验报告一-常用命令使用.doc