tarjan基于这样一个定理:
在任何深度优先搜索中,同一强连通支内的所有顶点均在同一棵深度优先树中。也就是说,强连通分量一定是有向图的某个深搜树子树。
既然强连通分量是深搜树的一棵子树,要找到一个分量,只要找到树根( 连接不同分量的桥的前端顶点) ,然后取出其所属分量的顶点即可。
引理:白色路径定理:
在一个有向或无向图G=(V,E)的深度优先森林中,结点v是结点u的后代当且仅当在搜索发现u的时刻d[u],从结点u出发经一条仅由白色结点组成的路径可达v。
所以,tarjan算法可以在线性时间内求出一个图的强连通分量,伪代码如下:
stack s;
graph G;
int dex;
tarjan(结点 u)
{
low(u) = dfu[u] = dex++;
s.push(u);
for (每一个 结点u 能到达的 结点v)
{
if(v 没有被搜到)
{
tarjan(v);
low[u] = min(low[u],low[v]);
}
else
low[u] = min(low[u],dfu[v]);
}
if (low[u] == dfu[u])
出栈直到元素为u;
}
当然,实际操作的时候会麻烦一点,实际用的时候一般伴随连通环压缩成点,加上求环的度,这都是一些技巧的问题了,就不再多说了!
今天用十字链表写了pku 2186题竟然用了400多ms,太失败了!郁闷。。。。