网络流及几种算法FF、EK、Dinic

news2024/12/23 12:05:34

终于要开始学习&&复习这个知识点了,说句实话半年多之前就该写这篇文章来加强理解,但是一直没有落实,因为又去练习了很多学过的算法,感觉这个算法不太常用哦,传说中的省选算法,比赛比较少见(可能是开不到吧。。。),想把这些东西和思维融为一体确实不容易,那么这就开始吧

网络流

  • 简介
  • Ford-Fulkerson
    • Edmonds–Karp算法
  • Dinic

简介

  • 如下图, s s s是起点, t t t是终点,其中边权表示每条管道中水的最大流量 ( c a p a c i t y ) (capacity) (capacity),问从 s s s t t t一次最多能送多少水
  • 我们还要介绍另外两个概念,残留量 ( r e s i d u a l ) (residual) (residual),也就是空闲量,即当前管道里面还能加入多少水,因为开始的时候管道里面水量是 0 0 0,所以一开始管道的空闲量为最大流量;流量 f l o w flow flow,也就是管道里面实际有多少的水,所以对于每条管道,有 f l o w = c a p a c i t y − r e s i d u a l flow=capacity-residual flow=capacityresidual
  • 我们想一下怎么解决这个问题,或许我们会想到一种办法,寻找一条从 s s s t t t的路径,那么这条路径上面边权最小的那条边权就是路径的瓶颈,也就是这条路径的 f l o w flow flow,这个想法是对的,但是我们接下来怎么办呢,如果再以类似的方法去找另外的路径这样得到的结果不一定是最优,所以引入了反向路径这个概念来解决这个问题

在这里插入图片描述

Ford-Fulkerson

  • F F FF FF方法的思路和前面提到的想法有些类似,我们从 s s s出发,随便找一条能够到达 t t t的简单路径,找到路径中的最小值,把整条路经所有边的边权都减去这个值,如果减为 0 0 0,那么视为删除这条边,同时这条路径上的所有边都重新建立一条反向路径,边权和这个最小边权的权值相等,这样就可以起到一个反悔的作用,能够证明这种方法总能够找到最优解
  • 上面的这个过程叫做找从 s s s t t t的一个增广路,也就是路径上的边的容量都要 > 0 >0 >0
  • 比如上面的图我找到了一条从起点到终点的增广路 s → 1 → 3 → t s\rightarrow1\rightarrow3\rightarrow t s13t,因为这里面最小的容量是 2 2 2,所以接下来的图就会是下面这个样子,红色边表示添加的反向边,这样一直找到再也没有 s s s t t t的简单路径,把每次减去的容量加在一起就是最大流
    在这里插入图片描述
  • 这种算法的时间复杂度是 O ( f × m ) O(f\times m) O(f×m) f f f表示最大网络流, m m m表示边数,因为采用 d f s dfs dfs进行搜索,可能会出现每次搜索只能增加 1 1 1的贡献,导致速度很慢

Edmonds–Karp算法

  • E K EK EK算法是 F F FF FF思想的实现方式,它采用 b f s bfs bfs而非 d f s dfs dfs进行搜索,好处是不会陷入某条边的漩涡中,时间复杂度能达到 O ( m 2 n ) O(m^2n) O(m2n) m m m表示边数, n n n表示点数

https://www.luogu.com.cn/problem/P3376

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

int main(){
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int n, m, s, t;
  cin >> n >> m >> s >> t;
  vector<vector<ll> > g(n + 1, vector<ll>(n + 1));
  for(int i=0;i<m;i++){
    int u, v, w;
    cin >> u >> v >> w;
    g[u][v] += w;
  }
  vector<ll> flow(n + 1);
  vector<int> pre(n + 1);
  function<ll(int, int)> Bfs = [&](int s, int t){
    queue<int> q;
    fill(pre.begin(), pre.end(), -1);
    q.push(s);
    int ans = 0;
    flow[s] = LONG_LONG_MAX;
    pre[s] = 0;
    while(!q.empty()){
      int u = q.front();
      q.pop();
      for(int i=1;i<=n;i++){
        if(pre[i] == -1 && g[u][i] != 0 && i != s){
          q.push(i);
          flow[i] = min(flow[u], g[u][i]);
          pre[i] = u;
        }
      }
    }
    if(pre[t] == -1) return -1ll;
    return flow[t];
  };
  function<ll(int, int)> maxFlow = [&](int s, int t){
    ll ans = 0;
    while(1){
      ll flow = Bfs(s, t);
      if(flow == -1ll) break;// 找不到增广路
      int cur = t;
      while(cur != s){
        int fa = pre[cur];
        g[fa][cur] -= flow;
        g[cur][fa] += flow;
        cur = fa;
      }
      ans += flow;
    }
    return ans;
  };
  cout << maxFlow(s, t) << '\n';
  return 0;
}

Dinic

  • 这个算法相对于之前的 E K EK EK算法改进点在于它使用了一个 O ( n 2 ) O(n^2) O(n2)构造的分层图,所谓分层就是按照它到源点的最短距离分成若干层,然后只能在层间转移而不能在层内转移
  • 这种算法的时间复杂度在使用弧优化的前提下是 O ( n 2 m ) O(n^2m) O(n2m)的, D f s Dfs Dfs O ( m ) O(m) O(m) B f s Bfs Bfs O ( n 2 ) O(n^2) O(n2)
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int V = 1225;
const int E = 1e5 + 3e4;
struct Edge{
  int nxt;
  int to;
  ll val;
}edge[E << 1];
int cnt = 2;
int head[V];
void Add_Edge(int u, int v, ll w){
  edge[cnt].nxt = head[u];
  edge[cnt].to = v;
  edge[cnt].val = w;
  head[u] = cnt++;
}
int dep[V];
int cur[V];
bool Bfs(int s, int t){
  memset(dep, 0, sizeof dep);
  queue<int> q;
  q.push(s);
  dep[s] = 1;
  while(!q.empty()){
    int u = q.front();
    q.pop();
    for(int i=head[u];i;i=edge[i].nxt){
      int v = edge[i].to;
      if(dep[v] == 0 && edge[i].val > 0){
        dep[v] = dep[u] + 1;
        q.push(v);
        if(v == t) return true;
      }
    }
  }
  return false;
}
ll Dfs(int u, int t, ll mf){
  if(u == t) return mf;
  ll sum = 0;
  for(int i=cur[u];i;i=edge[i].nxt){
    cur[u] = i;// 当前弧优化
    int v = edge[i].to;
    if(dep[v] == dep[u] + 1 && edge[i].val > 0){
      ll f = Dfs(v, t, min(mf, edge[i].val));
      edge[i].val -= f;
      edge[i ^ 1].val += f;// 更新残留网络
      sum += f;
      mf -= f;
      if(mf == 0) break;// 余量为0
    }
  }
  if(sum == 0) dep[u] = 0;// 如果走不到终点, 说明这个点没用了
  return sum;
}
ll Dinic(int s, int t){
  ll flow = 0;
  while(Bfs(s, t)){
    memcpy(cur, head, sizeof head);
    flow += Dfs(s, t, INT_MAX);
  }
  return flow;
}
int main(){
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int n, m, s, t;
  cin >> n >> m >> s >> t;
  for(int i=0;i<m;i++){
    int u, v;
    ll w;
    cin >> u >> v >> w;
    Add_Edge(u, v, w);
    Add_Edge(v, u, 0ll);
  }
  cout << Dinic(s, t);
  return 0;
}

还有一种算法是 I S A P ISAP ISAP,复杂度是 O ( n m 2 ) O(nm^2) O(nm2),以后有时间再看吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/115226.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在2022 CCF上获得两项大奖!

喜报!      在日前举行的      2022全国高性能计算学术年会上      戴尔科技集团      获得两项大奖!      戴尔科技PowerEdge绿色数据中心      液冷解决方案荣获“解决方案奖”    PowerEdge R750 DAOS      高性能分布式存储系统荣获“产品…

基于springboot+mybatis+mysql+jsp网上书城管理系统

基于 springbootmybatismysqljsp 网上书城管理系统一、系统介绍二、功能展示1.主页(客户)2.登陆&#xff08;客户&#xff09;3.我的购物车(客户)4.我的订单&#xff08;客户&#xff09;5.我的图书&#xff08;商家&#xff09;6.新书上架&#xff08;商家&#xff09;7.订单管…

股指期货是怎么交易的?3分钟教你从入门到精通

相对比投资于单一的产品而言&#xff0c;越来越多的投资者开始爱上股指期货&#xff0c;因为指数的波动速度特别的快&#xff0c;再加上里面的收益空间也特别的饱满&#xff0c;所以这是绝大多数希望赚快钱的投资者最喜欢的类似期货、股票等产品。而且很多进入到这个市场的投资…

CodeQL代码静态污点分析引擎排查漏洞模式

文章目录前言环境搭建1.1 codeql基础1.2 vscode插件1.3 生成数据库1.4 HelloWorldcodeql语法2.1 语法结构2.2 常用类库2.3 谓词介绍2.4 污点分析漏洞检测3.1 初步结果3.2 解决误报总结前言 对于代码审计的工作&#xff0c;最早期的安全人员会以人工审计的方式来审计项目代码&a…

【学习笔记】jenkins持续集成入门

jenkins持续集成入门 文章目录学习源一、jenkins简介和安装安装&#xff1a;插件:安装插件&#xff1a;二、配置Jenkins系统邮箱三、使用jenkins实现持续集成&#xff08;一&#xff09;使用Jenkins实现简单的本地Python项目代码执行准备工作&#xff1a;使用Jenkins管理-手动构…

PHP开发工具PhpStorm v2022.3——完全支持PHP 8.2

PhpStorm是一个轻量级且便捷的PHP IDE&#xff0c;其旨在提高用户效率&#xff0c;可深刻理解用户的编码&#xff0c;提供智能代码补全&#xff0c;快速导航以及即时错误检查。可随时帮助用户对其编码进行调整&#xff0c;运行单元测试或者提供可视化debug功能。 PhpStorm v20…

PM说丨浅谈PDCA与Scrum的“异曲同工”之妙

文章目录一、前言二、PDCA与Scrum介绍1、 PDCA循环&#xff08;戴明环&#xff09;2、 Scrum三、PDCA与Scrum对比四、总结一、前言 笔者最近参与到一个生产制造型企业的ERP系统升级改造项目&#xff0c;实施过程中涉及到QMS与质量管理相关内容。 在了解质量管理体系的过程中发…

如何优雅地使用git?

文章目录Oh shit gitgitmojigit命令思维导图Oh shit git https://ohshitgit.com/ 这个网站针对一些在使用git中可能遇到的问题都做了详细介绍&#xff0c;并且形象生动。 例如&#xff1a;Oh shit&#xff0c;我想改个地方&#xff0c;但我已经提交&#xff08;commited&#…

现代C++ 05

智能指针与内存管理 1.1 RAII 与引用计数 了解 Objective-C/Swift 的程序员应该知道引用计数的概念。引用计数这种计数是为了防止内存泄露而产生的。 基本想法是对于动态分配的对象&#xff0c;进行引用计数&#xff0c;每当增加一次对同一个对象的引用&#xff0c;那么引用对…

云安全攻击手段及防御策略

恶意软件是我们必须面对的现实&#xff0c;我们每天都需要与蠕虫、病毒、间谍软件和其他行恶意软件作斗争&#xff0c;而云恶意软件是我们需要面对的又一种类别。它已经发展十多年&#xff0c;早在2011年就托管在亚马逊简单存储服务存储桶中。云安全提供商Netskope报告称&#…

SpringCloud01--黑马【上】

SpringCloud01 1.认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 1.0.学习目标 了解微服务架构的优缺点 1.1.单体架构 单体架构&#xff…

三菱FX5U系列PLC与汇川IT6000系列触摸屏进行MODBUS TCP通信的具体方法

三菱FX5U系列PLC与汇川IT6000系列触摸屏进行MODBUS TCP通信的具体方法 本次和大家分享三菱FX5U系列PLC与汇川IT6000系列触摸屏进行MODBUS TCP通信的具体方法,由于汇川IT6000系列触摸屏组态软件中没有三菱FX5U系列PLC的连接驱动,所以采用MODBUS TCP通信的方式实现。 具体步骤可…

黄海冷水区微生物群落的季节演替及温度响应模式

期刊&#xff1a;Applied and Environmental Microbiology 影响因子&#xff1a;5.005 发表时间&#xff1a;2022 样本类型&#xff1a;水体 客户单位&#xff1a;中国海洋大学 凌恩客户中国海洋大学发表在《Applied and Environmental Microbiology》上的文章…

vue3 antd项目实战——table表格 根据属性值设置背景颜色【rowClassName添加行样式 + /deep/样式穿透 + css不可控】

根据数据属性值添加table表格行样式&#xff08;rowClassName&#xff09;知识调用场景复现利用rowClassName编写行样式编写行样式函数➕筛选条件编写特定的行样式取消相应的斑马纹样式知识调用 文章中可能会用到的知识链接vue3ant design vuets实战【ant-design-vue组件库引入…

如何检测时间序列中的异方差(Heteroskedasticity)

时间序列中非恒定方差的检测与处理&#xff0c;如果一个时间序列的方差随时间变化&#xff0c;那么它就是异方差的。否则数据集是同方差的。 异方差性影响时间序列建模。因此检测和处理这种情况非常重要。 让我们从一个可视化的例子开始。 下面的图1显示了航空公司乘客的时间…

Zotero快速入门

文章目录一、前言二、下载和安装Zotero三、界面初识和基本操作3.1 创建分类3.2 文献导入3.2.1 自动导入3.2.2 手动导入3.3 内置pdf管理3.4 同步3.5 插件3.5.1 安装方法3.5.2 插件推荐四、与word/wps协同引用文献4.1 使用内置格式4.1.1 添加索引4.1.2 添加书目4.2 自定义格式4.2…

基于AD Event日志监测域内信息探测行为

01、简介当攻击者获得内网某台域内服务器的权限&#xff0c;就会以此为起始攻击点&#xff0c;尽可能地去收集域的信息&#xff0c;以获取域控权限作为内网的终极目标。例如&#xff0c;攻击者会在内网中收集域管理员用户列表和特定敏感用户的信息&#xff0c;通过定位域管理员…

【c++】STL--vector

前言 想必大家已经对string有所了解了&#xff0c;string是专门用于字符串的。今天讲到的vector则是表示可变大小数组的序列容器。就像数组一样&#xff0c;vectoer也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问&#xff0c;和数组…

从根本上理解Synchronized的加锁过程

伸手摘星&#xff0c;即使一无所获&#xff0c;亦不致满手污泥。 请关注公众号&#xff1a;星河之码 作为一个Java开发&#xff0c;对于Synchronized这个关键字并不会陌生&#xff0c;无论是并发编程&#xff0c;还是与面试官对线&#xff0c;Synchronized可以说是必不可少。 …

顶刊实证复现:金融投资行为与企业技术创新 -动机分析与经验证据(思路梳理+全数据源+python代码)

标题&#xff1a;金融投资行为与企业技术创新 ——动机分析与经验证据 参考文献 作者&#xff1a;段军山 庄旭东 数据概况 1、数据来源&#xff1a; 第三方数据库 2、样本&#xff1a;2009-2018 中国 A 股市场的上市公司科技数据和财务数据 3、数据处理&#xff1a; (1)由…