最大网络流算法之dinic算法
文章目录
- 最大网络流
- 深度优先搜索
- Dinic
- 第一个优化:高度数組
- 第二个优化
- 二、代码
最大网络流
首先要给出每一条线路的承载量,一定要把边都是有方向的。一定要指明一个源点跟目标点如图源点是A,目标点是D,如果从A点灌水,没一根关系都有它的承载量,问从A出发能灌多少水到D,整个流最大是多少?
深度优先搜索
朴素的深度优先遍历不行,会因为选边的顺序导致算不出正确答案
Dinic
Dinic算法的主线
它最普遍的一点就是它有一个负反馈路线,或者说他有一个隐含的路线。
如图最大流量为80
补反向边,也就是说你减少多少,你的反向边就增加多少
补反向边,不会让总答案变大,但是能解决反悔的问题
如果你是正常线路的话,增加反向边不会增大答案,但是会因此让已经错失的可能性给报回来
第一个优化:高度数組
建立高度,让我每一步往下推的代价,尽量的低
从A出发完宽度优先遍历。认为A的高度是0, BC的高度是1,D的高度是2
我有一个数组记录的每一个点的层数
当我这个A往下走的时候,只有层数变大的路我去选。
A到B能不能到?能到,A是0层B是1层,而且层数大了1
从B走的时候,B要不要到C层?不要,因为你俩层数一样,本身Dinic算法规避了回去的问题。
所以B发现C跟自己层数一样,这条路它就不会走,它直接从A到B到D,一条深度优先,然后从A到C到D
先建立起1个高度数组,玩DFS这样的一种机制本身可以避免来回走的问题。
第二个优化
有一个支路数组,记录着每一个点走到了哪条支路了
记录哪些数组用过了,不用再尝试
例如我们从a到d,其中第一条支路A->B->E->D 其中50这条支路还剩10,上面的支路已经走完了,不能再走了
接下来,A选择第二条线路如果我们有一个数组记录着某一个点之前哪些线路用过了,此时我就不用再看10用不用,20用不用,30用不用它们都跳过了,直接从没用完的边继续试。
二、代码
1城市拥有哪些边是一个list(),里头是边的编号每一个城市拥有边的编号,它其实在边数组里去找。
城市拥有哪些边是边的编号,这样有两个好处:
1.不影响我城市的跳转2.0,1 2,3 4,5…
一条边进来生成两条进入边数组里去,所以0,1互成反向,2,3互成反向,4,5互成反向号边的反向边就是i^1,特别方便找反向
public static class Edge {public int from;public int to;public int available;public Edge(int a, int b, int c) {from = a;to = b;available = c;}}public static class Dinic {private int N;private ArrayList<ArrayList<Integer>> nexts;private ArrayList<Edge> edges;private int[] depth;private int[] cur;public Dinic(int nums) {N = nums + 1;nexts = new ArrayList<>();for (int i = 0; i <= N; i++) {nexts.add(new ArrayList<>());}edges = new ArrayList<>();depth = new int[N];cur = new int[N];}public void addEdge(int u, int v, int r) {int m = edges.size();edges.add(new Edge(u, v, r));nexts.get(u).add(m);edges.add(new Edge(v, u, 0));nexts.get(v).add(m + 1);}public int maxFlow(int s, int t) {int flow = 0;while (bfs(s, t)) {Arrays.fill(cur, 0);flow += dfs(s, t, Integer.MAX_VALUE);Arrays.fill(depth, 0);}return flow;}private boolean bfs(int s, int t) {LinkedList<Integer> queue = new LinkedList<>();queue.addFirst(s);boolean[] visited = new boolean[N];visited[s] = true;while (!queue.isEmpty()) {int u = queue.pollLast();for (int i = 0; i < nexts.get(u).size(); i++) {Edge e = edges.get(nexts.get(u).get(i));int v = e.to;if (!visited[v] && e.available > 0) {visited[v] = true;depth[v] = depth[u] + 1;if (v == t) {break;}queue.addFirst(v);}}}return visited[t];}// 当前来到了s点,s可变// 最终目标是t,t固定参数// r,收到的任务// 收集到的流,作为结果返回,ans <= rprivate int dfs(int s, int t, int r) {if (s == t || r == 0) {return r;}int f = 0;int flow = 0;// s点从哪条边开始试 -> cur[s]for (; cur[s] < nexts.get(s).size(); cur[s]++) {int ei = nexts.get(s).get(cur[s]);Edge e = edges.get(ei);Edge o = edges.get(ei ^ 1);if (depth[e.to] == depth[s] + 1 && (f = dfs(e.to, t, Math.min(e.available, r))) != 0) {e.available -= f;o.available += f;flow += f;r -= f;if (r <= 0) {break;}}}return flow;}}public static void main(String[] args) {Scanner cin = new Scanner(System.in);int cases = cin.nextInt();for (int i = 1; i <= cases; i++) {int n = cin.nextInt();int s = cin.nextInt();int t = cin.nextInt();int m = cin.nextInt();Dinic dinic = new Dinic(n);for (int j = 0; j < m; j++) {int from = cin.nextInt();int to = cin.nextInt();int weight = cin.nextInt();dinic.addEdge(from, to, weight);dinic.addEdge(to, from, weight);}int ans = dinic.maxFlow(s, t);System.out.println("Case " + i + ": " + ans);}cin.close();}
最大网络流算法之dinic算法相关推荐
- 图论 —— 网络流 —— 最大流 —— Dinic 算法
[概述] Dinic 算法在 EK 算法的基础上进行了优化,其时间复杂度为 O(n*n*m). Dinic 在找增广路的时也是找最短增广路, 但与 EK 算法不同的是 Dinic 算法并不是每次 bf ...
- 网络流最大流 Dinic算法模板
Dinic算法跟EK算法的优化地方就在于,EK是每次bfs记录前驱结点,然后从汇点找到一条回到源点的路. 而dinic是bfs记录深度,不断从源点dfs到汇点并且更新路径流量,直到dfs不到汇点. 邻 ...
- 网络流最大流算法(ISAP算法及DINIC算法)
这些算法网络中解释都有,所有以下是根据题目应用,代码中有注释,方便理解,ISAP算法就是通过先bfs一遍建立逆序求层数,然后每次都进行维护求最短路来求增广路径,下次查找建立在上次查找的最小路径的源点进 ...
- hdu4280 Island Transport 网络流最大流 Dinic算法高效模板
Island Transport In the vast waters far far away, there are many islands. People are living on the i ...
- HDU3549(最大流算法的Dinic算法)
题目:Flow Problem #include <iostream> #include <stdio.h> #include <string.h> using n ...
- 网络流-最大流(Ford-Fulkerson算法Dinic算法)
文章目录 最大流 FF算法: 增广路: 反边: 代码: Dinic算法: Dinic + 当前弧优化 最大流 就如同水流,存在一张图,既有起点又有终点,从起点流向终点的最大流量就是最大流. 在上面的图 ...
- 图论:Dinic算法
解决最大流问题我搜到了一堆的算法:EK算法.FF算法.Dinic算法.SAP算法.ISAP算法 然而并没有什么鸟用 掌握最常见的Dinic就够了,据说极限优化的ISAP比Dinic更快一些..我当不知 ...
- 【网络流】最大流问题(EK算法带模板,Dinic算法带模板及弧优化,ISAP算法带模板及弧优化)上下界网络流
本blog重点是代码 网络流的相关概念 流网络(flow network) 流(flow) 网络的流 残留网络(residual network) 增广路径(augmenting path) Edmo ...
- Dinic算法(研究总结,网络流)
Dinic算法(研究总结,网络流) http://www.cnblogs.com/SYCstudio/p/7260613.html posted on 2018-08-23 17:45 Pyloj 阅 ...
最新文章
- hdu3790 最短路径问题(spfa)
- web developer tips (51):使用vs2005和IE8进行调试
- 四川大学计算机网络_四川大学20考研情况
- php制表网页打印到a4纸,A4纸网页打印 html网页页面的宽度设置成多少
- gson 入门_Google GSON入门
- 告别只会调参和调包,全球顶会论文审稿人带你7天玩转图像分割
- 再谈布局,栅栏式自适应布局的学习和实现(calc自适应布局)
- explict关键字
- 学习用TypeScript写React组件
- ReactNative 启动js server报错:Metro Bundler can't listen on port 8081
- 范围分区在数据过期化处理中的应用
- JQUERY-SELECT 实现下拉框可以搜索、选择
- 获取微信小程序码的“47001”错误码的坑,errmsg:data format error hint
- oracle g1 gc,G1 GC日志分析
- 用c语言屏蔽鼠标键盘,用VBS屏蔽键盘和鼠标
- 高级工程师职称计算机要求,高级工程师职称评定条件及流程
- 计算机声音音乐小星星,迷你世界电路音乐教学 小星星音乐电路
- 什么是Hadoop的HA机制?
- bbedit php,BBEdit for Mac(最好用的HTML文本编辑器)
- MEMS加速度计如何选型?