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

Tarjan全家桶系列--强联通分量

强联通分量(SCC)

有向图中的一个​​极大子图​,其中任意两个节点uv都​​互相可达​(即存在u→vv→u的路径),则这个子图为一个强联通分量
Tarjan 算法基于深度优先搜索(DFS),利用 DFS 序dfnlow链 来判断一个节点是否是某个强连通分量的“根”(即最早被访问的节点)。

基本定义:

强连通分量(SCC):有向图中,任意两个节点 u, v 互相可达的最大子图。
dfn[u]:节点 u 被 DFS 第一次访问的时间戳(DFS 序)。
low[u]:从 u 出发,通过若干条边(可以走树边、后向边、横叉边),能到达的所有节点中 最小的 dfn 值。
换句话说:low[u] = min{ dfn[v] | v 从 u 出发可达 }

关键性质:

如果在 DFS 回溯时发现low[u] == dfn[u],说明 u 是当前 SCC 的“根”。
因为从 u 出发无法回到比 u 更早访问的节点。
此时,从栈顶到 u 的所有节点构成一个 SCC。

栈的作用:

DFS 过程中,将访问的节点压入栈。
当找到一个 SCC 的根时,从栈中弹出直到 u,这些节点就属于同一个 SCC。

模板

说明:void Run(int _n,const vector<int>adj[])为传入点的数量,vector邻接表数组,运行求出所有强联通分量 。·vector<int> Get()为获取scc数组,即scc[i]i点属于的强连通分量编号

template<intN>structSCC{vector<int>scc;vector<int>stk;intdfn[N],low[N];constvector<int>*adj;intn,clk,tot;//tot:scc数量voiddfs(intu){++clk;dfn[u]=low[u]=clk;stk.push_back(u);for(intto:adj[u]){if(dfn[to]==-1){dfs(to);low[u]=min(low[u],low[to]);}elseif(scc[to]==-1)low[u]=min(low[u],dfn[to]);}if(low[u]==dfn[u]){intv=-1;++tot;do{v=stk.back();stk.pop_back();scc[v]=tot;}while(v!=u);}}voidRun(int_n,constvector<int>adj[]){n=_n;clk=tot=0;stk.clear();fill(low,low+3+n,-1);fill(dfn,dfn+3+n,-1);scc.assign(n+3,-1);this->adj=adj;for(inti=1;i<=n;++i)if(scc[i]==-1)dfs(i);}vector<int>Get(){returnscc;}};

使用示例

template<intN>structSCC{vector<int>scc;vector<int>stk;intdfn[N],low[N];constvector<int>*adj;intn,clk,tot;//tot:scc数量voiddfs(intu){++clk;dfn[u]=low[u]=clk;stk.push_back(u);for(intto:adj[u]){if(dfn[to]==-1){dfs(to);low[u]=min(low[u],low[to]);}elseif(scc[to]==-1)low[u]=min(low[u],dfn[to]);}if(low[u]==dfn[u]){intv=-1;++tot;do{v=stk.back();stk.pop_back();scc[v]=tot;}while(v!=u);}}voidRun(int_n,constvector<int>adj[]){n=_n;clk=tot=0;stk.clear();fill(low,low+1+n,-1);fill(dfn,dfn+1+n,-1);scc.assign(n+3,-1);this->adj=adj;for(inti=1;i<=n;++i)if(scc[i]==-1)dfs(i);}vector<int>Get(){returnscc;}};constintmaxn=2*1e5+20;SCC<maxn>T;vector<int>e[maxn];intmain(){intn,m;//n个点,m条边for(inti=1;i<=m;++i){//输入m条边intu,v;cin>>u>>v;e[u].push_back(v);}T.Run(n,e);//跑tarjanvector<int>scc=T.Get();//获取scc数组,scc[i]=i点属于的强连通分量编号
http://www.gsyq.cn/news/93746.html

相关文章:

  • 学Simulink——基于高比例可再生能源渗透的复杂电网建模场景实例:大规模光伏并网对区域电网频率稳定影响研究
  • 校徽批评,何时从“找茬”走向“建设”?——兼评一篇公众号文章的逻辑
  • Profinet转Modbus TCP工业数据采集网关:实现1200PLC 与打标卡数据实时传输
  • Git能上传多大的文件
  • 3.7 Elasticsearch-查询性能剖析:profile API、DFS query_then_fetch
  • 国内纸纱线FSC春夏14至16针,实力公司推荐排行榜揭秘
  • 参数估计(三)-- 隐参数模型
  • 数据结构入门:从“是什么”到“为什么要学”
  • 国内专业纸纱线FSC春夏14-16针工厂,这份推荐榜单别错过
  • 黑神话 地图APP 程序
  • OKR与绩效考核结合:优势、挑战与实践路径
  • AD学习笔记-31 DRC检查
  • Linux系统编程——进程进阶:父子关系、终止与资源回收
  • 2025年GEO优化机会与争议以及规范发展的必要性
  • 2025最新!大模型学习路线图:超全超详细,从语言模型基础到LLM安全框架! - 详解
  • 压缩空气储能和释能阶段模型,附相关文档文献。 建立了压缩空气储能系统中的压缩机、换热器、储气罐...
  • 17. Qt深入 容器删除元素的异常处理
  • springboot公务员应届生复习备考平台_tm7d928l
  • C51_红外通信
  • JConsole 中 GC 时间统计的含义
  • LightModel
  • 说说ESim电工仿真软件
  • ModelEngine实战指南:从零开始构建智能对话应用
  • Profiling 专项
  • 旧物改造灵感库,核心功能,分享旧物改造案例,如塑料瓶做花盆,旧衣服改围裙等,支持搜索改造类型,上传自己的作品,应用场景,喜欢动手的中老年人找改造灵感,废物利用省钱又环保。
  • 如何全面评估大语言模型:从测试基准到性能优化的完整指南
  • 如何完成一个方便简单的Arduino共阳极数码管实验(从0~9依次循环亮起)
  • 基于php的幸运舞蹈工作室管理系统设计与实现(源码+lw+部署文档+讲解等)
  • 10分钟搞定HunyuanVideo部署:从零开始生成你的第一个AI视频
  • 基于php的微信小程序的学习交流平台系统(源码+lw+部署文档+讲解等)