tarjan算法用来求解一个有向图的强连通分量
算法要求我们
- 有$dfn$数组记录每一个节点在深度优先搜索中的访问次序
- $visited$数组作为全局变量,记录某一个节点是否被访问过
- $Stack$作为栈,储存在一次深度优先搜索中访问到的节点,$top$为栈顶指针,初始值为$-1$,$inStack$数组记录该节点是否在栈中
- $low$数组记录每一个节点能回溯到的最早访问到的节点
- $index$记录访问次序,初始值为0或者1
算法流程
对图中每一个节点进行访问,首先判断节点是否被访问过,也就是判断
如果该节点访问过就跳过该节点,否则就从这个节点开始深度优先搜索
1
| void DFS(int vertex,Gragh G)
|
进入深度优先搜索函数后,我们先进行以下赋值
1 2 3 4
| visited[vertex]=1; dfn[vertex]=low[vertex]=index++; Stack[++top]=vertex; inStack[vertex]=1;
|
然后我们对该节点的所有相邻节点进行深度优先访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| PtrToV p; for(p=G->VertexArr[vertex];p!=NULL;p=p->next){ if(!visited[p->vert]){ DFS(p->vert,G); low[vertex] = min(low[vertex],low[p->vert]) } else if(inStack[p->vert]){ low[vertex]=min(low[vertex],dfn[p->vert]) } } if(dfn[vertex]==low[vertex]){ while(Stack[top]!=vertex){ v=Stack[top--]; print(v); } }
|
完整代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| void DFS(int vertex,Graph G,void(*visit)(Vertex V)); int min(int a,int b); int dfn[2*MaxVertices],low[2*MaxVertices],visited[2*MaxVertices],Stack[2*MaxVertices],top=-1,index=0,inStack[2*MaxVertices]; int min(int a,int b){ return (a<b)?a:b; } void StronglyConnectedComponents( Graph G, void (*visit)(Vertex V) ){ for(int i=0;i<G->NumOfVertices;++i){ if(visited[i]==0){ DFS(i,G,visit); } } } void DFS(int vertex,Graph G,void(*visit)(Vertex V)){ visited[vertex]=inStack[vertex]=1; dfn[vertex]=low[vertex]=index++; Stack[++top]=vertex; PtrToVNode p; for(p = G->Array[vertex];p != NULL;p=p->Next){ if(!visited[p->Vert]){ DFS(p->Vert,G,visit); low[vertex]=min(low[vertex],low[p->Vert]); } else if(inStack[p->Vert]){ low[vertex] = min(low[vertex],dfn[p->Vert]); } } if(dfn[vertex]==low[vertex]){ while (Stack[top]!=vertex) { visit(Stack[top]); inStack[Stack[top]]=0; top--; } visit(Stack[top]); inStack[Stack[top]]=0; top--; printf("\n"); } }
|