定义dfn[]为每个点的时间戳(搜索次序),low[]为每个点的所能追溯到的,最低dfn的祖先的dfn,也就是最浅祖先
证明我真的不会,只能自己YY,不确保说的每句话都是正确的,如果我的分析有错误请一定要指出来!!!
先走dfs。一个有SCC的图一定有环,所以当搜索到一个已经到过的点时,我们就找到了一个环,此时这个环上所有的点一定都强联通(就好比地球是圆的,所以一直沿某个方向是可以回到起点的),这个环就是一个强联通子图,我们最后找的就是一个极大的环。
用栈保存读入的点,每遇到一个dfn==low的点,就说明找到了这个环的祖先,将这个祖先以及后于其加入栈的点弹出来,并且标记flag[弹出的点]=false,
flag用来确保把某个环剔出去,这样在求其他的环时就不会因为环上某条指向应该被删除的某个环的单向边而被影响。
void tarjan(int x) {
dfn[x] = low[x] = ++count;
s[++top] = x;
flag[x] = 1;
for(int i=last[x]; i; i=e[i].next){
int v = e[i].to;
if(!dfn[v]) {
tarjan(v);
if(low[x] > low[v])
low[x] = low[v];
}
else if(dfn[v] < low[x] && flag[v])
low[x] = dfn[v];
}
if(dfn[x] == low[x]) {
int j, k = 0;
sccnum++;
do{
j = s[top--];
flag[j] = 0;
k++;
}while(j!=x);
}
}

本文介绍了一种使用Tarjan算法寻找图中的强连通分量的方法。通过深度优先搜索(DFS)来标记每个节点的时间戳和可达最浅祖先,进而找到所有强连通子图。
5158

被折叠的 条评论
为什么被折叠?



