首页
/
行业洞察
/
正文
INDUSTRY INSIGHT · 深度
洛谷 B3609:[图论与代数结构 701] 强连通分量 ← Kosaraju 算法
📅 2026/9/11 19:44:30
✍️ 爱科研究院
👁 阅读 3,247
【题目来源】https://www.luogu.com.cn/problem/B3609【题目描述】给定一张 n 个点 m 条边的有向图求出其所有的强连通分量。注意本题可能存在重边和自环。【输入格式】第一行两个正整数 nm表示图的点数和边数。接下来 m 行每行两个正整数 u 和 v 表示一条边。【输出格式】第一行一个整数表示这张图的强连通分量数目。接下来每行输出一个强连通分量。第一行输出 1 号点所在强连通分量第二行输出 2 号点所在强连通分量若已被输出则改为输出 3 号点所在强连通分量以此类推。每个强连通分量按节点编号大小输出。【输入样例】6 81 21 52 65 66 15 36 43 4【输出样例】31 2 5 634【数据范围】对于所有数据1≤n≤100001≤m≤100000。【算法分析】Kosaraju 算法是一种用于查找有向图中强连通分量Strongly Connected Components, SCC的经典算法。它的核心思想是通过两次深度优先搜索DFS来实现时间复杂度为 O(VE)其中 V 是顶点数E 是边数。Kosaraju 算法模板题代码详见https://blog.csdn.net/hnjzsyjyj/article/details/164698263● 算法步骤一第一次 DFS正向图对原始有向图进行 DFS 遍历记录每个顶点的完成时间即退出递归的顺序。将顶点按完成时间的逆序压入一个栈中完成时间越晚的顶点越早入栈。二转置图构建原图的转置图将所有边的方向反转。三第二次 DFS反向图从栈顶依次弹出顶点对转置图进行 DFS。每次 DFS 访问到的所有顶点构成一个强连通分量。● 为什么有效第一次 DFS 确定了顶点的拓扑顺序基于完成时间。转置图将原图中的强连通分量内部的环保持不变但改变了不同分量之间的连接方向。第二次 DFS 在转置图上按逆序访问可以确保每次只探索同一个强连通分量内的顶点不会跨到其他分量。【算法代码】#includebits/stdc.h using namespace std; const int N1e55; vectorint G[N],G2[N]; vectorint group[N]; int st[N]; int post[N],post_cnt; int scc[N],scc_cnt; void dfs1(int u) { st[u]1; for(int v:G[u]) { if(!st[v]) dfs1(v); } post[post_cnt]u; } void dfs2(int u) { st[u]1; scc[u]scc_cnt; group[scc_cnt].push_back(u); for(int v:G2[u]) { if(!st[v]) dfs2(v); } } void kosaraju(int n) { memset(st,0,sizeof st); post_cnt0; for(int i1; in; i) { if(!st[i]) dfs1(i); } memset(st,0,sizeof st); scc_cnt0; for(int ipost_cnt; i1; i--) { int upost[i]; if(!st[u]) { scc_cnt; dfs2(u); } } } int main() { ios::sync_with_stdio(0); cin.tie(0); int n,m; cinnm; for(int i1; im; i) { int x,y; cinxy; G[x].push_back(y); G2[y].push_back(x); } kosaraju(n); vectorvectorint all_scc; for(int id1; idscc_cnt; id) { sort(group[id].begin(), group[id].end()); all_scc.push_back(group[id]); } int totalall_scc.size(); for(int i0; itotal; i) { for(int ji1; jtotal; j) { int aall_scc[i][0]; int ball_scc[j][0]; if(ab) swap(all_scc[i],all_scc[j]); } } coutall_scc.size()\n; for(int i0; iall_scc.size(); i) { for(int j0; jall_scc[i].size(); j) { coutall_scc[i][j] ; } cout\n; } return 0; } /* in: 6 8 1 2 1 5 2 6 5 6 6 1 5 3 6 4 3 4 out: 3 1 2 5 6 3 4 */【参考文献】https://blog.csdn.net/hnjzsyjyj/article/details/164698263https://blog.csdn.net/hnjzsyjyj/article/details/164631569
📌 标签:
工业官网
设计趋势
AI 建站
SEO
获取完整报告 →
RELATED ARTICLES
推荐阅读
2026/9/11 19:44:30
湖南交通职院单招全面解析|报考形势、上岸难点与科学备考攻略
2026/9/11 19:39:29
音频处理实战|翻唱伴奏升降调要移几个调?音域匹配与移调损耗的四个判断
2026/9/11 19:39:29
西门子PLC智能喷泉控制系统设计与实现
2026/9/11 20:19:32
职责链模式及其C++实现变体详解
2026/9/11 20:19:32
Java+Swing+MySQL停车场管理系统:从数据库设计到并发控制
2026/9/11 20:19:32
60文件级改造实测:七款AI编程助手谁真正扛得住复杂工程
2026/9/11 20:19:32
STM32F407六足机器人嵌入式系统实战指南
2026/9/11 20:19:32
Semantic Kernel 多智能体编排(Multi-agent Orchestration)架构解析与实践指南
2026/9/11 20:14:31
Matplotlib Axes API深度解析与高级可视化技巧
2026/9/11 0:02:03
数据容灾核心指标与实战方案解析
2026/9/11 0:02:03
Huly 平台 ClickUp 任务导入实战指南:从 CSV 导出到一键迁移全流程解析
2026/9/11 0:02:03
PyTorch 构建与代码生成工具链深度解析:从 tools 目录看懂构建流程、autograd/JIT 代码生成与 HIPify 移植
2026/9/11 5:40:15
超人会飞不算本事:系统稳定依赖清晰规则与边界设计
2026/9/11 8:29:24
超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论
2026/9/11 9:11:20
基于CNN的调制信号识别:MATLAB实现时频图分类实战