Dinic 算法(优化)

前言: (个人而言)
  1. dfs_test()我以前学然后写Dinic中的dfs用来增广

  2. 新的dfs()速度比原来快很多

    1. 判断 向下增广返回的流是否为0

    2. 返回的流不为0代表增广成功 维护边后直接回溯

    3. 原来的dfs_test处于一个点时 : 只要所有出边遍历结束才回溯,


优化

  1. 当前弧优化 :
  1. 原来的dfs都是从每个点的第一条边开始遍历,导致已经增广过的边会被重复dfs
  2. 开一个cur[]记录每一个点当前增广到的边,当其他的dfs增广到的时候,从有效的边开始增广,
  • bfs分层后初始化cur[], 即head[]每个点的第一条边,
  1. 分层优化(说法不一,其他blog学习到的,下同): bfs分层时找到汇点直接退出
  2. 剩余量优化: 用不到我新学的dfs上, 但是原来的dfs_test可以优化

需要Dinic优化才能过 且 建图巧妙 luogu P1361 最小割

  1. 源点s∈Ss \in Ss∈S,源点和每个点连边代表在SSS部分的收益, 同理汇点t∈Tt \in Tt∈T,每个点和汇点连边代表处于TTT部分的收益

  2. 建虚点 处理部分点所在的点集处于图的2个部分的额外收益

    1. 点集看做2个点,在SSS部分时, 源点向虚点 连边且边权代表额外收益,
    2. 如何处理,点集中任意一个点不在此集合中会额外收益也消失
    3. 虚点连向点集中每个点一条边权为无穷的边,
    4. 当点集中的点被割到另一集合中时,这条inf的边使得源点和虚点的边(额外收益)的边也被割掉
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3010;
const int maxm = 2e6+5;
const int inf  = 0x3f3f3f3f;
struct Edge {int v,c,next;
} edge[maxm];int n,m,tot,source,sink,cnt;
int head[maxn],dep[maxn],cur[maxn];void add(int u,int v,int c) {edge[tot].v=v; edge[tot].c=c;edge[tot].next=head[u]; head[u]=tot++;
}
void addedge(int u,int v,int c) {add(u,v,c);add(v,u,0);
}bool bfs() {queue<int> que;memset(dep,-1,sizeof dep);dep[source] = 0;que.push(source);while (!que.empty()) {int u = que.front(); que.pop();for (int i=head[u]; i!=-1; i=edge[i].next) {int to = edge[i].v;if (edge[i].c>0 && dep[to] == -1) {dep[to] = dep[u] + 1;que.push(to);// 找到汇点直接退出 优化2if (to == sink) return 1;}}}return dep[sink] != -1;
}int dfs(int u,int dist) {if (u == sink)return dist;for (int &i=cur[u]; i!=-1; i=edge[i].next) { // 通过引用更新cur[]:记录每个点当前增广的边int to = edge[i].v;if (edge[i].c>0 && dep[to]==dep[u]+1) {int temp = dfs(to,min(dist,edge[i].c));if (temp > 0) {edge[i].c -= temp;edge[i^1].c += temp;return temp;}}}return 0;
}int dfs_test(int u,int delta) {if (u == sink)return delta;int flow = 0;for (int &i=cur[u]; i!=-1; i=edge[i].next) {int to = edge[i].v;if (edge[i].c>0 && dep[to]==dep[u]+1) {int temp = dfs(to,min(delta-flow,edge[i].c));edge[i].c   -= temp;edge[i^1].c += temp;flow += temp;// 没有流量就打破循环 优化3if (delta-flow <= 0) break;}}if (!flow) dep[u] = -1;return flow;
}int Dinic() {int ans = 0;while (bfs()) { for (int i=0; i<cnt; ++i) // 分层后每个点当前增广到的边当然是第一条边cur[i] = head[i];while(1) {int temp = dfs(source,inf);//int temp = dfs_test(source,inf);if (!temp) break;ans += temp;}}return ans;
}int main() {memset(head,-1,sizeof head);scanf("%d",&n);source = 0;sink = n+1;int tot_val = 0;for (int i=1; i<=2*n; ++i) {int val; scanf("%d",&val);tot_val += val;if (i <= n) {addedge(source,i,val);} else {addedge(i-n,sink,val);}}scanf("%d",&m);cnt = sink+1;for (int i=1; i<=m; ++i) {int k,c1,c2,to;//cin >> k >> c1 >> c2;scanf("%d%d%d",&k,&c1,&c2);tot_val += (c1+c2);addedge(source,cnt++,c1);addedge(cnt++, sink, c2);while (k--) {//cin >> to;scanf("%d",&to);addedge(cnt-2,to,inf);addedge(to,cnt-1,inf);}}int maxflow = Dinic();//cout << tot_val-maxflow << endl;printf("%d\n",tot_val - maxflow);return 0;
}

Dinic算法 (优化)相关推荐

  1. 【网络流】最大流问题(EK算法带模板,Dinic算法带模板及弧优化,ISAP算法带模板及弧优化)上下界网络流

    本blog重点是代码 网络流的相关概念 流网络(flow network) 流(flow) 网络的流 残留网络(residual network) 增广路径(augmenting path) Edmo ...

  2. 网络流最大流 Dinic算法模板

    Dinic算法跟EK算法的优化地方就在于,EK是每次bfs记录前驱结点,然后从汇点找到一条回到源点的路. 而dinic是bfs记录深度,不断从源点dfs到汇点并且更新路径流量,直到dfs不到汇点. 邻 ...

  3. 图论:Dinic算法

    解决最大流问题我搜到了一堆的算法:EK算法.FF算法.Dinic算法.SAP算法.ISAP算法 然而并没有什么鸟用 掌握最常见的Dinic就够了,据说极限优化的ISAP比Dinic更快一些..我当不知 ...

  4. Dinic算法----最大流常用算法之一

    --没有什么是一个BFS或一个DFS解决不了的:如果有,那就两个一起. 最大流的$EK$算法虽然简单,但时间复杂度是$O(nm^2)$,在竞赛中不太常用. 竞赛中常用的$Dinic$算法和$SAP$, ...

  5. 最大流EK和Dinic算法

    最大流EK和Dinic算法 EK算法 最朴素的求最大流的算法. 做法:不停的寻找增广路,直到找不到为止 代码如下: @Frosero #include <cstdio> #include ...

  6. 图论 —— 网络流 —— 最大流 —— Dinic 算法

    [概述] Dinic 算法在 EK 算法的基础上进行了优化,其时间复杂度为 O(n*n*m). Dinic 在找增广路的时也是找最短增广路, 但与 EK 算法不同的是 Dinic 算法并不是每次 bf ...

  7. 网络流-最大流(Ford-Fulkerson算法Dinic算法)

    文章目录 最大流 FF算法: 增广路: 反边: 代码: Dinic算法: Dinic + 当前弧优化 最大流 就如同水流,存在一张图,既有起点又有终点,从起点流向终点的最大流量就是最大流. 在上面的图 ...

  8. 最大流算法模板:EK和dinic算法

    最大流算法模板:EK和dinic算法 一.EK算法模板 #include<iostream> #include<queue> using namespace std; cons ...

  9. 最大网络流算法之dinic算法

    文章目录 最大网络流 深度优先搜索 Dinic 第一个优化:高度数組 第二个优化 二.代码 最大网络流 首先要给出每一条线路的承载量,一定要把边都是有方向的.一定要指明一个源点跟目标点如图源点是A,目 ...

最新文章

  1. 2021年大数据Kafka(四):❤️kafka的shell命令使用❤️
  2. 个人对计算机知识产权的理解,知识产权的一种多元解释
  3. 能进这个Java组织的都是大神,现在只有三个中国人
  4. 关于SAP Commerce Cloud CORS policy的设置问题
  5. 数据轮播图翻页封装(左右点击)
  6. jquery 获取easyui combobox选中的值
  7. 计算机视觉论文-2021-09-10
  8. 【Level 08】U08 Positive Attitude L5 Satisfy your need to know
  9. mysql 执行计划 视频_MySQL执行计划的讲解
  10. cocos2d-x3.10 适配 IPV6
  11. g++ vscode 环境选择_VSCode C++环境配置(个人使用)
  12. oracle12 group by 拼接字符串
  13. Photon Release 4.8.0汉化(附图教程)
  14. 系统架构设计:平滑发布和 ABTesting,你都会吗?
  15. 智能电视聚好看连接服务器失败,智能电视为什么登录失败? 试试这样做
  16. 只会写代码的程序员不是好程序员
  17. 计算机桌面任务栏怎样显示输入法,计算机中任务栏的输入法无法切换怎么处理...
  18. 海洋cms单本小说网站模板
  19. 将数据库的数据导入es中
  20. Atlas2.1.0实战:安装、配置、导入hive元数据、编译排坑

热门文章

  1. 我们该如何看待加密VC青睐的那些NFT项目?
  2. linux下修改或删除包含乱码、特殊符号等文件名的文件
  3. 一针见血的工作励志语录
  4. 通过mvn命令上传jar包到nexus
  5. mvn 命令打包项目
  6. 基于LSSVM和PSO进行信号预测(Matlab代码实现)
  7. [C/C++语言基础] —函数
  8. android studio 光标 输入法,解决IDEA2018.1.5或者Android Studio 3.0版本的输入法不跟随光标问题...
  9. X64驱动开发和保护+X86X64游戏逆向分析课程
  10. 桌球游戏小项目及注意事项