当前位置: 首页 > news >正文

完整教程:Articulation Point(割点)算法详解

Articulation Point(割点)算法详解

割点(Articulation Point) 是图论中的一个非常经典的问题:
在无向图中,如果删除某个顶点会导致图不连通,则该顶点就是一个割点。

本篇文章将基于 TheAlgorithms/Go 实现的版本,对代码进行完整中文解读,并详细解释其中的 DFS(深度优先搜索)与“时间戳”逻辑,从而帮助读者彻底理解割点的判断方式。


一、Articulation Point(割点)是什么?

我们在图中找一个点,如果删掉这个点(以及与它相连的边),图会被拆成多个不连通部分,那么这个点就是“割点”。

例如:

A - B - C - D|E

顶点 B 是割点,因为删除 B 后,E 会与其他点断开。

割点广泛用于:

  • 网络可靠性分析
  • 社交网络关键人物分析
  • 通信链路的冗余分析
  • 强连通性算法
  • 拓扑结构弱点定位

二、算法基础:DFS + 时间戳(Tarjan 思想)

算法核心思想:

  1. 对每个节点 DFS 编号,得到 discovery time
  2. 同时计算每个节点能回退到的最早时间戳 low-link(earliest discovery)
  3. 如果满足:

low[child] >= disc[parent]

parent 是一个割点

代表:子节点无法通过回边访问到父节点之前的节点 → 割裂发生

特殊规则:


三、代码中文翻译(逐行解释版)

下面是你给出的代码的中文翻译版+中文注释。


✨ 代码中文翻译与注释

// Package graph 提供图结构分析相关的算法。
package graph
import "github.com/TheAlgorithms/Go/math/min"
// apHelper 用于在搜索割点过程中存储辅助数据。
type apHelper struct {
isAP              []bool // 标记每个顶点是否为割点
visited           []bool // DFS 是否访问过
childCount        []int  // 每个顶点的子节点数(仅 DFS 树意义)
discoveryTime     []int  // DFS 遍历时节点的发现时间戳
earliestDiscovery []int  // 能回退到的最早时间(low-link 值)
}
// ArticulationPoint 用于寻找图中的割点。
// 返回一个布尔切片,表示每个顶点是否是割点。
// 时间复杂度:O(|V| + |E|)
// 空间复杂度:O(|V|)
func ArticulationPoint(graph *Graph) []bool {
// time 用于记录 DFS 访问时间戳
time := 0
// apHelper 结构初始化
apHelperInstance := &apHelper{
isAP:              make([]bool, graph.vertices),
visited:           make([]bool, graph.vertices),
childCount:        make([]int, graph.vertices),
discoveryTime:     make([]int, graph.vertices),
earliestDiscovery: make([]int, graph.vertices),
}
// 从根节点 0 开始 DFS
articulationPointHelper(apHelperInstance, 0, -1, &time, graph)
// 根节点如果只有一个孩子,则不能视为割点
if apHelperInstance.childCount[0] == 1 {
apHelperInstance.isAP[0] = false
}
return apHelperInstance.isAP
}
// articulationPointHelper 通过 DFS 遍历图并标记割点。
// 更新 childCount、discoveryTime 和 earliestDiscovery。
func articulationPointHelper(
apHelperInstance *apHelper,
vertex int,
parent int,
time *int,
graph *Graph,
) {
apHelperInstance.visited[vertex] = true
// 设置发现时间和最早可回退时间
apHelperInstance.discoveryTime[vertex] = *time
apHelperInstance.earliestDiscovery[vertex] = *time
*time++
for nextVertex := range graph.edges[vertex] {
// 跳过父节点
if nextVertex == parent {
continue
}
if apHelperInstance.visited[nextVertex] {
// 遇到回边,更新 low-link
apHelperInstance.earliestDiscovery[vertex] = min.Int(
apHelperInstance.earliestDiscovery[vertex],
apHelperInstance.discoveryTime[nextVertex],
)
continue
}
// 作为 DFS 子节点计数
apHelperInstance.childCount[vertex]++
articulationPointHelper(apHelperInstance, nextVertex, vertex, time, graph)
// DFS 完成后更新 earliestDiscovery
apHelperInstance.earliestDiscovery[vertex] = min.Int(
apHelperInstance.earliestDiscovery[vertex],
apHelperInstance.earliestDiscovery[nextVertex],
)
// 满足割点条件
if apHelperInstance.earliestDiscovery[nextVertex] >= apHelperInstance.discoveryTime[vertex] {
apHelperInstance.isAP[vertex] = true
}
}
}

四、算法关键逻辑解析

1. discoveryTime(发现时间)

DFS 每访问一个节点,会赋予一个递增时间戳。

例如:

0 → 1 → 3 → 4 → 2

发现时间可能是:

disc = [0, 1, 4, 2, 3]

2. earliestDiscovery(low-link 值)

表示该节点通过“回边”能跳到的最早祖先。

计算方式:

earliest[v] = min(earliest[v], discovery[u])

或在 DFS 回溯时更新:

earliest[parent] = min(earliest[parent], earliest[child])

3. 割点判定条件

非根节点

如果:

low[child] >= disc[parent]

则 parent 是割点。

因为 child 无法回到 parent 之前 → 删除 parent 会断链。


4. 根节点单独判断

根节点必须有 两个及以上子树 才是割点。


五、图示理解(低值回退)

节点 A → B → C
如果 C 有一条边连回 A,则 low[C] 会是 disc[A],因此 B 不是割点

A
| \
|  C
|
B

六、总结

名称含义
discoveryTimeDFS 第几次访问到
earliestDiscovery(low-link)能回退到的最早祖先
childCount根节点割点判定专用
isAP是否为割点

算法性能:

  • 时间复杂度:O(V + E)
  • 空间复杂度:O(V)
  • 使用 DFS + Tarjan 思想,是最优解法
http://www.jsqmd.com/news/360772/

相关文章:

  • 通俗理解记忆网络(Memory Network)——从0到1彻底掌握End-to-End MemNN
  • SMUDebugTool:破解硬件稳定性难题的底层调试方案
  • 2026年靠谱的光敏实物印章,无锡宜兴实物印章,公安备案实物印章厂家推荐及采购参考 - 品牌鉴赏师
  • 训练稳定性保障:微调过程中的梯度爆炸与Loss发散排查
  • 最全自学黑客技术学习路线,少走弯路
  • 安装Pspice成功要点
  • 拖延症福音!专科生专属降AI神器 —— 千笔·专业降AI率智能体
  • 编译错误:将当前用户的默认 Shell 切换为 bash
  • 通俗理解消息传递机制
  • 《内网安全攻防.渗透测试实战指南》学习笔记一:内网渗透基础
  • office PPT文件瘦身
  • 毕业论文神器!千笔·降AI率助手,全网顶尖的降AI率软件
  • 简易黑客初级教程:黑客技术,分享教学
  • 2026更新版!9个一键生成论文工具:研究生毕业论文+开题报告高效写作测评
  • UE 自定义Plugins插件遇到的问题
  • 好写作AI:当文学遇见算法,如何让创意与效率“双向奔赴”?
  • ELK 搭建实战:从 0 到 1 打通日志收集、分析与可视化
  • 渗透神器 - BurpSuite - 基础篇
  • 2026年甲级监理公司推荐:权威评测与排名,直击项目管理效率与安全痛点 - 品牌推荐
  • 新手必刷的五个渗透测试靶场(建议收藏)
  • 终止代码: STORE DATA_STRUCTURE CORRUPTION
  • 股票智能预测系统(Python代码,可以自主选择预测模型,被预测的为每天的收盘价格,代码有详细注释),很容易替换为其它时序数据集,其它模型也很容易被加进去,已经留了增加其它模型的位置
  • springboot 整合 druid
  • 价值两万美元的复制粘贴失误:当HackerOne“黑”了自己
  • 第三方评估报告哪家可靠?2026年第三方评估公司全面评测与推荐,直击独立性与专业性痛点 - 品牌推荐
  • 2026年西安靠谱的结婚礼品店排名,特色礼品店口碑哪家好 - 工业设备
  • 考古级揭秘:网络安全工程师,你真的了解DOS系统吗?(别告诉我你只知道“攻击”)
  • 剖析成人高考知名的教学机构,济南万汇教育值得选吗? - 工业品网
  • 轴承故障诊断(一维时序信息结合二维图像实现故障诊断,python编程,十分类,每行代码都有详细中文注释,Tensorflow框架)
  • 2026年防火铝塑板厂家推荐:多行业应用横向对比排名,涵盖交通与家具领域安装痛点 - 品牌推荐