Dinic算法 (优化)
Dinic 算法(优化)
前言: (个人而言)
dfs_test()
是 我以前学然后写Dinic
中的dfs
用来增广新的
dfs()
速度比原来快很多判断 向下增广返回的流是否为0
返回的流不为0代表增广成功 维护边后直接回溯
原来的
dfs_test
处于一个点时 : 只要所有出边遍历结束才回溯,
优化
- 当前弧优化 :
- 原来的dfs都是从每个点的第一条边开始遍历,导致已经增广过的边会被重复dfs
- 开一个
cur[]
记录每一个点当前增广到的边,当其他的dfs增广到的时候,从有效的边开始增广,
bfs
分层后初始化cur[]
, 即head[]
每个点的第一条边,
- 分层优化(说法不一,其他blog学习到的,下同):
bfs
分层时找到汇点直接退出 - 剩余量优化: 用不到我新学的
dfs
上, 但是原来的dfs_test
可以优化
需要Dinic优化才能过 且 建图巧妙 luogu P1361 最小割
源点s∈Ss \in Ss∈S,源点和每个点连边代表在SSS部分的收益, 同理汇点t∈Tt \in Tt∈T,每个点和汇点连边代表处于TTT部分的收益
建虚点 处理部分点所在的点集处于图的2个部分的额外收益:
- 点集看做2个点,在SSS部分时, 源点向虚点 连边且边权代表额外收益,
- 如何处理,点集中任意一个点不在此集合中会额外收益也消失
- 虚点连向点集中每个点一条边权为无穷的边,
- 当点集中的点被割到另一集合中时,这条
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算法 (优化)相关推荐
- 【网络流】最大流问题(EK算法带模板,Dinic算法带模板及弧优化,ISAP算法带模板及弧优化)上下界网络流
本blog重点是代码 网络流的相关概念 流网络(flow network) 流(flow) 网络的流 残留网络(residual network) 增广路径(augmenting path) Edmo ...
- 网络流最大流 Dinic算法模板
Dinic算法跟EK算法的优化地方就在于,EK是每次bfs记录前驱结点,然后从汇点找到一条回到源点的路. 而dinic是bfs记录深度,不断从源点dfs到汇点并且更新路径流量,直到dfs不到汇点. 邻 ...
- 图论:Dinic算法
解决最大流问题我搜到了一堆的算法:EK算法.FF算法.Dinic算法.SAP算法.ISAP算法 然而并没有什么鸟用 掌握最常见的Dinic就够了,据说极限优化的ISAP比Dinic更快一些..我当不知 ...
- Dinic算法----最大流常用算法之一
--没有什么是一个BFS或一个DFS解决不了的:如果有,那就两个一起. 最大流的$EK$算法虽然简单,但时间复杂度是$O(nm^2)$,在竞赛中不太常用. 竞赛中常用的$Dinic$算法和$SAP$, ...
- 最大流EK和Dinic算法
最大流EK和Dinic算法 EK算法 最朴素的求最大流的算法. 做法:不停的寻找增广路,直到找不到为止 代码如下: @Frosero #include <cstdio> #include ...
- 图论 —— 网络流 —— 最大流 —— Dinic 算法
[概述] Dinic 算法在 EK 算法的基础上进行了优化,其时间复杂度为 O(n*n*m). Dinic 在找增广路的时也是找最短增广路, 但与 EK 算法不同的是 Dinic 算法并不是每次 bf ...
- 网络流-最大流(Ford-Fulkerson算法Dinic算法)
文章目录 最大流 FF算法: 增广路: 反边: 代码: Dinic算法: Dinic + 当前弧优化 最大流 就如同水流,存在一张图,既有起点又有终点,从起点流向终点的最大流量就是最大流. 在上面的图 ...
- 最大流算法模板:EK和dinic算法
最大流算法模板:EK和dinic算法 一.EK算法模板 #include<iostream> #include<queue> using namespace std; cons ...
- 最大网络流算法之dinic算法
文章目录 最大网络流 深度优先搜索 Dinic 第一个优化:高度数組 第二个优化 二.代码 最大网络流 首先要给出每一条线路的承载量,一定要把边都是有方向的.一定要指明一个源点跟目标点如图源点是A,目 ...
最新文章
- 2021年大数据Kafka(四):❤️kafka的shell命令使用❤️
- 个人对计算机知识产权的理解,知识产权的一种多元解释
- 能进这个Java组织的都是大神,现在只有三个中国人
- 关于SAP Commerce Cloud CORS policy的设置问题
- 数据轮播图翻页封装(左右点击)
- jquery 获取easyui combobox选中的值
- 计算机视觉论文-2021-09-10
- 【Level 08】U08 Positive Attitude L5 Satisfy your need to know
- mysql 执行计划 视频_MySQL执行计划的讲解
- cocos2d-x3.10 适配 IPV6
- g++ vscode 环境选择_VSCode C++环境配置(个人使用)
- oracle12 group by 拼接字符串
- Photon Release 4.8.0汉化(附图教程)
- 系统架构设计:平滑发布和 ABTesting,你都会吗?
- 智能电视聚好看连接服务器失败,智能电视为什么登录失败? 试试这样做
- 只会写代码的程序员不是好程序员
- 计算机桌面任务栏怎样显示输入法,计算机中任务栏的输入法无法切换怎么处理...
- 海洋cms单本小说网站模板
- 将数据库的数据导入es中
- Atlas2.1.0实战:安装、配置、导入hive元数据、编译排坑
热门文章
- 我们该如何看待加密VC青睐的那些NFT项目?
- linux下修改或删除包含乱码、特殊符号等文件名的文件
- 一针见血的工作励志语录
- 通过mvn命令上传jar包到nexus
- mvn 命令打包项目
- 基于LSSVM和PSO进行信号预测(Matlab代码实现)
- [C/C++语言基础] —函数
- android studio 光标 输入法,解决IDEA2018.1.5或者Android Studio 3.0版本的输入法不跟随光标问题...
- X64驱动开发和保护+X86X64游戏逆向分析课程
- 桌球游戏小项目及注意事项