【算法】Tarjan算法求强连通分量
2024-09-06 11:27:21
概念:
- 在有向图G中,如果两个定点u可以到达v,并且v也可以到达u,那么我们称这两个定点强连通。
- 如果有向图G的任意两个顶点都是强连通的,那么我们称G是一个强连通图。
- 一个有向图中的最大强连通子图,称为强连通分量。
tarjan的主要思想:
从一个点开始DFS,记录两个数组,dfn[]和low[]。
其中,dfn[i]指的是到达第i个点的时间。
low[i]指第i个点直接或间接可到达的点中的最小dfn[j]。
low[i]数组的初始值为dfn[i]。
举个例子,如图所示:
假如我们从第一个点开始跑DFS,dfn[1]=1,low[1]=1;那么走到第2个点时,标记dfn[2]=2;第三个点dfn[3]=2;dfn[4]=3;dfn[5]=3;dfn[6]=4;
同时,我们也可以得到另一个数组low[]:
low[1]=1;low[2]=1;low[3]=1;low[4]=1;low[5]=3;low[6]=4;
推广:
对于每一个没有被遍历到的点u,如果从当前点有一条到未遍历点u的有向边,则遍历到u,同时将点u入栈,时间戳+1并用dfn[u]记录到达点u的时间,枚举从u发出的每一条边,如果该边指向的点没有被访问过,那么继续dfs,回溯后low[u]=min(low[u],low[v])(其中v为u可以到达的点。)如果该点已经访问过并且该点仍在栈里,那么low[u]=min(low[u],dfn[v])。
证明:
略,作为一名OIer,知道结论就行了!!!
代码:
void tarjan(int u)
{
low[u]=dfn[u]=++tim;
instack[u]=1;stk[top++]=u;
for(int i=H[u];i;i=X[i])
{
int v=P[i];
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(instack[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
cnt++;
int k;
do
{
siz[cnt]++;
k=stk[--top];
belong[k]=cnt;
instack[k]=0;
}
while(k!=u);
}
}
例题:
最新文章
- 表单中Readonly和Disabled的区别
- asp.net设置默认打开页面,Web.config,defaultDocument
- MVC页面重定向'页面跳转
- mysql数据库优化小结
- [AngularJS + Webpack] Using Webpack for angularjs
- js获取ip方法
- Baidu百度搜索引擎登录网站 - Blog透视镜
- JQuery学习笔记——层级选择器
- Linux项目自动部署
- mysql MHA扩展haproxy搭建从库只读负载均衡
- Bom简单介绍
- 清北学堂 清北-Day1-R2-监听monitor
- 初窥Java--1(下载JADK,搭建环境变量)
- Docker入门2------容器container常规操作
- WinForm将一个窗体的值传到另一个窗体的listbox控件,C#
- 多线程——继承Thread类实现一个多线程
- Zuul Pre和Post过滤器
- BZOJ 2745: [HEOI2012]Bridge
- C++报错集锦
- STL中关联式容器的特性
热门文章
- Circle of Monsters(贪心)
- Spring官网阅读(十八)Spring中的AOP
- NEON中的L可以避免溢出
- Redis学习笔记(二) 链表
- 构建自己的专用OpenCV----记录一次由applyColorMap()引发的探索
- [CodeForces 300C Beautiful Numbers]组合计数
- Python内置函数列表
- 切片原型[start:stop:step]
- Spring Boot 之 Spring Batch 批处理实践
- Postman学习之Authorization