Tarjan
来源:互联网 发布:两期二叉树模型 知乎 编辑:程序博客网 时间:2024/05/22 12:56
Tarjan 算法
一.算法简介
Tarjan 算法一种由Robert Tarjan提出的求解有向图强连通分量的算法,它能做到线性时间的复杂度。
我们定义:
如果两个顶点可以相互通达,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量(strongly connectedcomponents)。
例如:在上图中,{1 , 2 , 3 , 4 } , { 5 } , { 6 } 三个区域可以相互连通,称为这个图的强连通分量。
Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。
再Tarjan算法中,有如下定义。
DFN[ i ] : 在DFS中该节点被搜索的次序(时间戳)
LOW[ i ] : 为i或i的子树能够追溯到的最早的栈中节点的次序号
当DFN[ i ]==LOW[ i ]时,为i或i的子树可以构成一个强连通分量。
二.算法图示
以1为Tarjan 算法的起始点,如图
顺次DFS搜到节点6
回溯时发现LOW[ 5 ]==DFN[ 5 ] , LOW[ 6]==DFN[ 6 ] ,则{ 5 } , { 6 } 为两个强连通分量。回溯至3节点,拓展节点4.
拓展节点1 , 发现1再栈中更新LOW[ 4 ],LOW[ 3 ] 的值为1
回溯节点1,拓展节点2
自此,Tarjan Algorithm 结束,{1 , 2 , 3 , 4 } , { 5 } , { 6 } 为图中的三个强连通分量。
不难发现,Tarjan Algorithm 的时间复杂度为O(E+V).
1. #include<iostream>
2. using namespace std;
3. int DFN[105]; //记录在做dfs时节点的搜索次序
4. int low[105]; //记录节点能够找到的最先访问的祖先的记号
5. int count=1; //标记访问次序,时间戳
6. int stack[105]; //压入栈中
7. int top=-1;
8. int flag[105]; //标记节点是否已经在栈中
9. int number=0;
10.int j;
11. int matrix[105][105]={{0,1,1,0,0,0},{0,0,0,1,0,0},{0,0,0,1,1,0},{1,0,0,0,0,1},{0,0,0,0,0,1},{0,0,0,0,0,0}};
12.int length; //图的长度
13. void tarjan(int u){
14. DFN[u]=low[u]=count++; //初始化两个值,自己为能找到的最先访问的祖先
15. stack[++top]=u;
16. flag[u]=1; //标记为已经在栈中
17.
18. for(int v=0;v<length;v++){
19. if(matrix[u][v]){
20. if(!DFN[v]){ //如果点i没有被访问过
21. tarjan(v); //递归访问
22. if(low[v]<low[u])
23. low[u]=low[v]; //更新能找的到祖先
24. }
25. else{ //如果访问过了,并且该点的DFN更小,则
26. if(DFN[v]<low[u]&&flag[v]) //flag[v]这个判断条件很重要,这样可以避免已经确定在其他联通图的v,因为u到v的单向边而影响到u的low
27. low[u]=DFN[v]; //也就是已经确定了的联通图要剔除掉,剔除的办法就是判断其还在栈中,因为已经确定了的连通图的点
28. } //flag在下面的do while中已经设为0了(即已经从栈中剔除了)
29. }
30. }
31.
32. //往后回溯的时候,如果发现DFN和low相同的节点,就可以把这个节点之后的节点全部弹栈,构成连通图
33. if(DFN[u]==low[u]){
34. number++; //记录连通图的数量
35. do{
36. j=stack[top--]; //依次取出,直到u
37. cout<<j<<" ";
38. flag[j]=0; //设置为不在栈中
39. }while(j!=u);
40. cout<<endl;
41. }
42.}
43. int main(){
44.
45. memset(DFN,0,sizeof(DFN)); //数据的初始化
46. memset(low,0,sizeof(low));
47. memset(flag,0,sizeof(flag));
48.
49. length=6;
50. tarjan(0);
51.
52. cout<<endl;
53. for(int i=0;i<6;i++){
54. cout<<"DFN["<<i<<"]:"<<DFN[i]<<" low["<<i<<"]:"<<low[i]<<endl;
55. }
56. return 0;
57. }
- tarjan
- Tarjan
- Tarjan
- tarjan
- tarjan
- tarjan
- Tarjan
- Tarjan
- Tarjan
- Tarjan
- Tarjan
- tarjan
- Tarjan
- Tarjan
- Tarjan
- tarjan
- tarjan算法
- hdoj1269 Tarjan
- 肠道内营养
- 手机应用分类
- Xcode8提交APP以后,在iTunes connect构建版本中不显示
- cookie、session学习笔记
- Spark Job Scheduling
- Tarjan
- C# 13位时间戳
- python模拟掷骰子
- 机器学习算法笔记之5:支持向量机SVM
- C# Winform 窗体美化(四、镂空窗体)
- 尊重个人劳动成果,如果可以请点赞,顶一下,谢谢!
- 2017上半年课程设计递推斐波那契
- java中的值传递和引用传递
- 炒蘑菇