Tarjan学习笔记
众所周知,Tarjan 可以用来求有向图的强连通分量,我们就不扯那些 dfs 生成树,前向边、返祖边之类的东西,直接步入正题。
准备工作
Tarjan 算法本质上是一次 dfs 的过程,我们用
正式开始
考虑从一个结点
- 如果
在栈中(即那个节点还没计算完),那么 一定是 的祖先,则用 更新 。 - 如果
访问过且不在栈中(即计算完了),那么装作无事发生。 - 如果
还没被访问过,那么递归访问,用 更新 。
将
在这个图中,
这时候,我们就可以处理
如果一个结点算完后
代码实现
//num记录当前一共遍历了几个结点,用于计算新结点的dfn
//col[i]记录第节点i在哪个强连通分量里,root[i]表示i所在强连通分量的根
//colnum记录当前一共算完了几个强连通分量,用来计算新强连通分量的编号
int tarjan(int now) {
s.push(now),vis[now]=1;
low[now]=dfn[now]=++num;
for(int i=head[now];i;i=e[i].next)
if(!dfn[e[i].to])
low[now]=min(low[now],tarjan(e[i].to));
else if(vis[e[i].to])
low[now]=min(low[now],dfn[e[i].to]);
if(dfn[now]==low[now]) {
vis[now]=0;
col[now]=++colnum,root[now]=now;
while(s.top()!=now) {
col[s.top()]=colnum,root[s.top()]=now;
vis[s.top()]=0,s.pop();
}
s.pop();
}
return low[now];
}
扩展阅读
建议参考阅读这篇文章的手动模拟算法的部分,会有更直观的理解。
有兴趣看看更严谨的说明,请上 oi-wiki 观看。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步