tarjan算法是由Robert Tarjan提出的求解有向图强连通分量的算法。

那么问题来了找蓝翔!(划掉)什么是强连通分量?

我们定义:如果两个顶点互相连通(即存在A到B和B到A的通路),则称这两个点强连通。对于一个有向图G,若是G中任意两点都强连通,则称G是一个强连通图。有向图的极大强连通子图,称为该图的强连通分量

对于下图,{1,2,3,4}、{5}、{6}分别是它的强连通分量。

【小白入门向】tarjan算法+codevs1332上白泽慧音 题解报告

那么tarjan是如何找到这些强连通分量的呢?

说白了tarjan就是dfs,每个强连通分量都是搜索树中的一颗子树。搜索时,我们把当前搜索树中未处理过的点加入一个堆栈,回溯时从栈顶依次取出元素判断他们是否属于一个强连通分量。

我们对dfs的过程中添加如下定义:
1、dfn[i]:代表搜索点i的次序编号;

2、low[i]:代表点i所能回溯到的栈中最早的次序编号。

当dfn[i]=low[i]时,以i为根的子树上的所有点便构成一个强连通分量。

 

二、tarjan算法c语言实现

那么要如何使用程序来实现tarjan算法呢?

大致思路如下:
1、从一个未被处理过的点i开始,给它结合一个次序编号并把它压入栈中,然后标记点表示其已入栈,令low[i]=dfn[i]=次序编号;

2、遍历每条以i为起点的边,若边的终点j未被处理过,就对其进行操作1~3,令low[i]=min(low[i],low[j]);

3、找到的点j若是被处理过,则判断其是否在栈中:若在,则令low[i]=min(low[i],dfn[j]);

4、若是dfn[i]=low[i],就将栈顶到i间的所有元素弹出,它们便是一个强连通分量;

5、重复1~4,直至不存在点未被处理。

贴上伪代码(转自百度百科词条——tarjan算法)

 1 tarjan(u)
 2 {
 3     DFN[u]=Low[u]=++Index//为节点u设定次序编号和Low初值
 4     Stack.push(u)//将节点u压入栈中
 5     for each(u,v) in E//枚举每一条边
 6         if (visnotvisted)//如果节点v未被访问过
 7             tarjan(v)//继续向下找
 8             Low[u]=min(Low[u],Low[v])
 9         else if (vinS)//如果节点v还在栈内
10                 Low[u]=min(Low[u],DFN[v])
11     if (DFN[u]==Low[u])//如果节点u是强连通分量的根
12     repeat{
13         v=S.pop//将v退栈,为该强连通分量中一个顶点
14         printv
15         until(u==v)
16     }
tarjan伪代码

相关文章:

  • 2022-12-23
  • 2021-09-19
  • 2022-02-05
  • 2021-08-25
  • 2021-07-27
  • 2021-06-20
猜你喜欢
  • 2022-01-28
  • 2021-06-17
  • 2022-12-23
  • 2022-12-23
  • 2021-12-11
  • 2021-08-17
相关资源
相似解决方案