这里参考几篇博客。留个坑,等下次自己把原理总结一下。如果需要快速了解。可以把这几个博客看一下:
csdn原理讲的很清楚
视频讲解,绘图一下就明白了
扩展内容
模板
Tarjan算法
可以在 O(n+m)O(n+m) 时间内求出有向图的所有强联通分量。
Tarjan算法伪代码
tarjan(u)
{
dfn[u]=low[u]=++Index
stack.push(u)
for each (u, v) in E
if (v is not visted)
tarjan(v)
low[u] = min(low[u], low[v])
else if (v in S)
low[u] = min(low[u], dfn[v])
if (dfn[u] == low[u])
repeat
v = stack.pop
print v
until (u== v)
}
C++模板
// N 表示点数,M 表示边数
int h[N], e[M], ne[M], cnt; // 存储有向图, h[]需要初始化成-1
int belong[N], stap[N], stop, instack[N], dfn[N], low[N], bent, dindex ;
// bent存储强联通分量的个数,belong[i] 存储第i个点处于哪个强联通分量中
void add (int a, int b)
{
e[cnt] = b ; ne[cnt] = h[a] ; h[a] = cnt ++ ;
}
void tarjan (int i)
{
dfn[i] = low[i] = ++ dindex ;
instack[stap[ ++ stop] = i] = 1 ;
for (int p = h[i]; p != -1; p = ne[p])
{
int j = e[p] ;
if (!dfn[j])
{
tarjan (j) ;
if (low[j] < low[i]) low[i] = low[j] ;
}
else if (instack[j] && dfn[j] < low[i]) low[i] = dfn[j] ;
}
if (dfn[i] == low[i])
{
++ bent ;
int j;
do
{
j = stap[stop -- ] ;
instack[j] = 0 ;
belong[j] = bent ;
} while (j != i) ;
}
}
练习题: