有向图的强连通分量: Kosaraju算法和Tarjan算法详解

在上一篇文章中, 我们了解了图的最小生成树算法. 本节我们来学习 图的强连通分量(Strongly Connected Component, SCC) 算法.

什么是强连通分量?

有向图 中, 若一组节点内的任意两个节点都能通过路径互相到达(例如 A → B A \rightarrow B AB B → A B \rightarrow A BA), 则这组节点构成一个强连通分量. 它是图中的最大独立连通单元, 可以看作一种对有向图结构的深层划分.


环境要求

本文所用样例在Windows 11以及Ubuntu 24.04上面编译通过.

  1. Windows: 使用[Visual Studio],
  2. Ubuntu: 使用 Clang 18.1.3. (Ubuntu 24.04 系统安装版本)
  3. GCC 无法编译直接本项目代码, 因为本文代码使用了 C++20 Module, 而 GCC 对此支持不完整.

关于 Module 的更多信息, 请参考我之前的博客: CMake 构建 C++20 Module 实例(使用 MSVC)

本项目工程目录: 图论代码


基础概念

在深入算法之前, 我们需要明确几个关键术语和背景知识.

有向图与强连通性

  • 强连通性(Strong Connectivity): 若图中任意两节点均能互相到达(即存在 A → B A \rightarrow B AB , B → A B \rightarrow A BA的路径), 则该图是强连通的.

    connected graph

    上图中任意两点都是强连通的.

  • 强连通分量(SCC): 有向图的子集, 其内部节点强连通, 且无法再添加任何其他节点仍保持强连通性(即"最大性").

    scc

    上图中强连通分量为 {1, 2, 3}


逆图(Transpose Graph)

将原图所有边的方向反转后得到的新图. 例如, 若原图有边 A → B A \rightarrow B AB, 逆图中则为: B → A B \rightarrow A BA. 在 Kosaraju 算法中, 逆图帮助定位 SCC 的"边界".

transpose


缩点(Condensation)与 DAG

缩点操作是将每个 SCC 合并为一个超级节点, 原图中 SCC 间的边简化为超级节点间的边. 缩点后的图无环路, 这一特性在拓扑排序中至关重要. 通过缩点, 复杂图的分析可简化为对 DAG 的操作(例如路径查找或依赖解析).
condensation


3. Kosaraju 算法详解

Kosaraju 算法是计算强连通分量(SCC)的高效算法, 时间复杂度为 O ( V + E ) O(V + E) O(V+E)(线性时间). 其核心思想通过两次深度优先搜索(DFS)实现, 结合逆图(Transpose Graph)和栈(Stack)的特性, 逐层剥离 SCC.

算法步骤

  1. 第一次 DFS: 标记节点完成顺序

    • 对原图进行深度优先搜索, 按节点完成遍历的逆序将节点压入栈(即最后完成的节点在栈顶).
    • 关键作用: 确保后续处理时, 从"最晚完成"的节点(即潜在 SCC 的"根")开始, 保证 SCC 的完整性.
  2. 构建逆图

    • 将原图所有边的方向反转, 生成逆图(Transpose Graph).
  3. 第二次 DFS: 提取 SCC

    • 按栈中节点的顺序, 依次从栈顶取出节点, 对逆图进行 DFS.
    • 每轮 DFS 访问的节点构成一个 SCC.
原理剖析
  • 为何需要逆图?
    SCC 的强连通性在逆图中保持不变, 但逆图的遍历顺序能天然隔离不同 SCC 的边界.

    • 例如, 原图中存在 A→B, 逆图中则为 B→A. 若 AB 属于同一 SCC, 逆图的 DFS 仍能覆盖两者; 若属于不同 SCC, 逆图的遍历顺序会避免跨分量污染.
  • 栈的作用
    第一次 DFS 的逆序栈隐含了原图的拓扑排序(忽略环路), 确保第二次 DFS 从"高层级"分量开始, 避免重复遍历.


伪代码实现

Kosaraju(G):// G 是一个有向图// Step 1: 对原图G执行深度优先搜索,并记录每个节点的完成时间finish_time = [] // 这里我们用一个列表存储按完成时间排序的节点visited = [false] * |V| // 初始化所有节点为未访问状态for each vertex u in G:if not visited[u]:DFS(G, u, visited, finish_time)// Step 2: 转置图G,得到G^TGT = transpose(G)// 重置访问标记数组visited = [false] * |V|// Step 3: 对转置后的图GT执行深度优先搜索,按照原图的完成时间顺序while finish_time is not empty:v = finish_time.pop() // 取出最后一个元素,即具有最大完成时间的节点if not visited[v]:// 打印或处理这个强连通分量print("SCC:")DFS(GT, v, visited) // 注意这里不需要更新finish_time// 深度优先搜索辅助函数
DFS(graph, start_vertex, visited, finish_time=None):visited[start_vertex] = truefor each neighbor in graph.adjacent(start_vertex):if not visited[neighbor]:DFS(graph, neighbor, visited, finish_time)if finish_time is not None:finish_time.append(start_vertex) // 在递归返回时记录节点

示例演示

假设原图如下(边为有向):

example

  1. 第一次 DFS: 假设遍历顺序为 A -> B -> C -> D -> E -> F, 栈中顺序为 栈底[F, E, D, C, B, A]栈顶.

    kosaraju first dfs

  2. 构建逆图: 所有边反转.
    kosaraju transpose

  3. 第二次 DFS: 依次弹出栈顶元素处理, 并 DFS 逆图:

    • A 出发, DFS 访问 A -> C -> B, 组成 SCC {A, B, C}.

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何为自己的 PDF 文件添加密码?在线加密 PDF 文件其实更简单

随着信息泄露和数据安全问题的日益突出,保护敏感信息变得尤为重要。加密 PDF 文件是一种有效的手段,可以确保只有授权用户才能访问或修改文档内容。本文将详细介绍如何使用 CleverPDF 在线工具为你的 PDF 文件添加密码保护,确保其安全性。 为…

面向机器学习的Java库与平台简介、适用场景、官方网站、社区网址

Java机器学习的库与平台 最近听到有的人说要做机器学习就一定要学Python,我想他们掌握的知识还不够系统、不够全面。本文作者给大家介绍几种常用Java实现的机器学习库,快快收藏加关注吧~ Java机器学习库表格 Java机器学习库整理库/平台概念…

Kubernetes 使用 Kube-Prometheus 构建指标监控 +飞书告警

1 介绍 Prometheus Operator 为 Kubernetes 提供了对 Prometheus 机器相关监控组件的本地部署和管理方案,该项目的目的是为了简化和自动化基于 Prometheus 的监控栈配置,主要包括以下几个功能: Kubernetes 自定义资源:使用 Kube…

Hadoop初体验

一、HDFS初体验 1. shell命令操作 hadoop fs -mkdir /itcast hadoop fs -put zookeeper.out /itcast hadoop fs -ls / 2. Web UI页面操作 结论: HDFS本质就是一个文件系统有目录树结构 和Linux类似,分文件、文件夹为什么上传一个小文件也这…

python: SQLAlchemy (ORM) Simple example using mysql in Ubuntu 24.04

mysql sql script: create table School 表 (SchoolId char(5) NOT NULL comment主鍵primary key,學校編號,SchoolName nvarchar(500) NOT NULL DEFAULT comment 學校名稱,SchoolTelNo varchar(8) NULL DEFAULT comment電話號碼,PRIMARY KEY (SchoolId) #主…

解放大脑!用DeepSeek自动生成PPT!

DeepSeek应用(PPT篇) DeepSeek作为当前最好的AI大模型之一,其强大的文本生成能力被广泛的应用于各个领域,本文我们来聊聊用DeepSeek来自动生成PPT。 一、DeepSeek & PPT DeepSeek本身没有直接生成PPT的能力,换个…

从0到1:固件分析

固件分析 0x01 固件提取 1、从厂商官网下载 例如D-link的固件: https://support.dlink.com/resource/products/ 2、代理或镜像设备更新时的流量 发起中间人攻击MITM #启用IP转发功能 echo 1 > /proc/sys/net/ipv4/ip_forward#配置iptables,将目…

docker独立部署milvus向量数据库

milvus镜像:国外封锁,国内源也不好用。基本上所有源都不能用 首先想到阿里云服务,但是阿里云国外服务器便宜的300~400呢。 基于成本考虑终于装上心心念念的milvus(*^▽^*) 安装 Milvus 安装 Milvus 独立版 wget https://raw.githubuserco…

宇树科技13家核心零部件供应商梳理!

2025年2月6日,摩根士丹利(Morgan Stanley)发布最新人形机器人研报:Humanoid 100: Mapping the Humanoid Robot Value Chain(人形机器人100:全球人形机器人产业链梳理)。 Humanoid 100清单清单中…

win10系统上的虚拟机安装麒麟V10系统提示找不到操作系统

目录预览 一、问题描述二、原因分析三、解决方案四、参考链接 一、问题描述 win10系统上的虚拟机安装麒麟V10系统提示找不到操作系统,报错:Operating System not found 二、原因分析 国产系统,需要注意的点: 需要看你的系统类…

C#初级教程(1)——C# 与.NET 框架:探索微软平台编程的强大组合

图片来源: https://www.lvhang.site/docs/dotnettimeline 即梦AI - 一站式AI创作平台 一、历史发展脉络 在早期的微软平台编程中,常用的编程语言有 Visual Basic、C、C。到了 20 世纪 90 年代末,Win32 API、MFC(Microsoft Found…

SpringBoot项目集成MinIO

最近在学习MinIO,所以想让自己的SpringBoot项目集成MinIO,在网上查阅资料,并进行操作的过程中遇到一些问题,所以想把自己遇到的坑和完成步骤记录下来供自己和各位查阅。 一. MinIO的下载安装以及基本使用 1. 下载地址:https://d…

ROS2下编写package利用orbbec相机进行yolov8实时目标检测

视频讲解 ROS2下编写package利用orbbec相机进行yolov8实时目标检测 在《ROS2下编写orbbec相机C package并Rviz显示》的基础上,继续添加对获取的图像使用YOLO进行目标检测 首先安装YOLO以及相关库 pip3 install ultralytics 使用如下指令测试下yolo安装情况 yol…

uniapp引入uview组件库(可以引用多个组件)

第一步安装 npm install uview-ui2.0.31 第二步更新uview npm update uview-ui 第三步在main.js中引入uview组件库 第四步在uni.scss中引入import "uview-ui/theme.scss"样式 第五步在文件中使用组件

UE5.3 C++ TArray系列(一)

一.TArray概述 它们就相当于C动态数组Vector,但是被UE封装了,懂得都懂反射嘛,要不一不小心就被回收了。 它真的非常常见,我所用的容器中,它绝对排名第一,第二是TMap。 同类好理解,我平时也常用…

R语言NIMBLE、Stan和INLA贝叶斯平滑及条件空间模型死亡率数据分析:提升疾病风险估计准确性...

全文链接:https://tecdat.cn/?p40365 在环境流行病学研究中,理解空间数据的特性以及如何通过合适的模型分析疾病的空间分布是至关重要的。本文主要介绍了不同类型的空间数据、空间格点过程的理论,并引入了疾病映射以及对空间风险进行平滑处理…

一款社交媒体中查用户名的工具

简介 追踪 400 多个社交网络中的用户名社交媒体账户以查找账户 安装 # python环境 pip安装 pip install sherlock-project # Mac环境 brew安装 brew install sherlock # docker安装 docker pull sherlock/sherlock 使用方式 ->$ sherlock -h usage: sherlock [-h] [-…

unity学习50:NavMeshAgent 区域Areas和cost

目录 1 NavMeshAgent 区域和成本的问题 2 区域Areas 2.1 区域和颜色 2.2 区域和成本 2.3 区域成本的作用 2.4 地图测试准备 2.5 如何实现 2.5.1 unity的2022之前的老版本 2.5.2 unity的2022之后的新版本 2.6 如果测试失败,是因为没有bake 2.7 测试前&…

JAVA版本游戏进程读写操作

1.导入游戏进程读写Maven依赖 <dependency><groupId>io.github.2lius</groupId><artifactId>MemoryProcess</artifactId><version>0.1</version></dependency> GitHub地址 2.代码操作游戏读写内存 package com.lius.test;impo…

英文字体:极简现代浓缩未来派科技海报标题排版无衬线字体 PODIUM Sharp Font

PODIUM Sharp 是 2012 年设计的 DUDU 字体的扩展版本。多年后&#xff0c;我决定通过添加新的母版和粗细来重建和开发这种字体。最后&#xff0c;PODIUM Sharp 由 234 种款式组成&#xff1a;从超压缩发际线到超扩展重度。 这个项目的主要目的是在我在旧波兰标本中发现的不同模…