尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Kosaraju 笔记

Kosaraju 笔记
📅 发布时间:2026/6/22 6:17:42

在做 ARC069F Flags 时看到有一个用 kosaraju 的 nb 做法,于是研究了一下 kosaraju。

Kosaraju 算法

kosaraju 算法是一种找出强连通分量的算法,用途和 tarjan 类似,但是代码更好写,并且在某些题上比 tarjan 算法有更多性质。

算法流程

  1. 对原图做一次 DFS:
    • 初始化一个栈 \(S\),
    • 对图中每个点未访问的点都 DFS 一遍,DFS 的时候像求 DFS 树一样,依次遍历 \(u\) 连接的没访问过的点 \(v\),并递归对 \(v\) 进行 DFS \(v\)。当 \(u\) 所有后继点都遍历完后,往栈 \(S\) 的栈顶加入 \(u\)。
  2. 按照栈中的顺序,在反图上做 DFS:
    • 维护一个标记数组以记录每个点所属的 SCC 编号。
    • 按照栈 \(S\) 中从栈顶到栈底的顺序依次取出结点 \(u\),若 \(u\) 未被标记则在反图上 DFS,并把每个 \(u\) 能到达的后继点的 SCC 编号标记为相同的编号。
    • 按照这个逻辑,则每次在反图上的 DFS 都能找出一个完整的 SCC。

代码:

//adj 是原图,nadj 是反图。void dfs1(int x) {vis[x] = 1;for (auto y : adj[x]) {if (!vis[y]) {dfs1(y);}}stk.push(x);
}
void dfs2(int x) {scc[x] = cid;for (auto y : nadj[x]) {if (!scc[y]) {dfs2(y);}}
}
void kosaraju() {for (int i = 1; i <= n; ++i) {if (!vis[i]) {dfs1(i);}}while (!stk.empty()) {int u = stk.top();stk.pop();if (!scc[u]) {++cid;dfs2(u);}}
}

算法正确性证明

引理:记结点 \(u\) 在栈中的位置为 \(f_u\)(栈顶的 \(f\) 值为 \(n\),栈底的 \(f\) 值为 \(1\)),所属的强连通分量编号为 \(C_u\),那么对于原图的一条边 \(u \to v\),若满足 \(C_u \ne C_v\),则有 \(f_u > f_v\) 成立。

证明:可以把每条跨 SCC 的边 \(u \to v\) 分为:\(u, v\) 在同一个 DFS 中遍历到的,和在不同 DFS 中遍历到的。(DFS 指代码中的 dfs1)

  • 对于被同一个 DFS 遍历到的,一定是先经过 \(u\) 再经过 \(v\),由于是后缀顺序遍历,所以越晚遍历到的点 \(f\) 值越小,故 \(f_u > f_v\) 成立。

  • 对于被不同 DFS 遍历到的,一定是先经过 \(v\) 再经过 \(u\),由于它们属于不同的 DFS 过程,先被 DFS 的 \(f\) 一定小,故 \(f_u > f_v\) 成立。

综上,原命题成立。

我们按照 \(f\) 从大到小在反图上 DFS,每次都只会遍历栈顶 \(u\) 所属强连通分量 \(C_u\) 中的点,因为 \(C_u\) 在 DAG 上的前驱点的 \(f\) 值都比 \(f_u\) 大,所以一定都在 \(u\) 之前被遍历过了。

可以注意到我们在根据拓扑序访问 DAG 上的强连通分量,所以求出的 SCC 编号从小到大排列就是 DAG 的拓扑序。(注意如果该算法用来实现 2-SAT,要与 Tarjan 算法的写法区分)

Flags

题意

给定 \(n\) 个二元组 \((x_i, y_i)\) 和 \(n\) 个数轴上的点,第 \(i\) 个点可以取在 \(x_i\) 或 \(y_i\),你需要求出一个方案使得 \(n\) 个点中相邻两个点的最小距离最大。

很明显可以先二分答案,然后转化成一个 2-SAT 问题,朴素的做法就是线段树优化建图 + Tarjan。

但是我们可以使用 Kosaraju,Kosaraju 在优化建图的问题上与 Tarjan 的区别就在于,Kosaraju 的形式很简洁,使得我们能够直接用数据结构优化 DFS 找点的过程,而不用像 Tarjan 一样建立虚点。通常情况下 Kosaraju 的时空常数都更好,部分情况下 Kosaraju 有复杂度更好的做法(有个点分树优化建图的题 Kosaraju 的复杂度更好,懒得放了)。

相关新闻

  • Python测试(上)_ 不存在不写bug的程序员
  • 用隐式马尔科夫模型检测XSS攻击Payload
  • mysql 查询今天、昨天、本周、上周、本月、上月、本季度、上季度、本年、上一年、的数据

最新新闻

  • 汽车贴玻璃膜品牌费用多少?靠谱的品牌分析 - myqiye
  • DeepSeek-V4架构解析:CSA、HCA与Muon三大认知计算原语
  • AI测试不是写用例,是重构测试工程师的思考链路
  • IDOR与XSS组合攻击:从漏洞原理到账户接管的实战剖析
  • 2026汽车贴玻璃膜公司哪家好?长春老蔡贴膜改装(炫途店)靠谱吗 - myqiye
  • Kimi K 2.5技术解析:多模态对齐与Agent Swarm工程实践

日新闻

  • 2026速览惠州叛逆青少年学校前十大排名名单出炉 - 武汉中职最新信息发布
  • 2026上饶白蚁消杀哪家好?15年本土2大权威白蚁防治公司推荐(金盾虫控/青蚁卫士) - 我叫一
  • 天龙八部单机版终极数据管理工具:5个技巧快速掌握游戏数据编辑

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号