您的位置:首页 > 其它

tarjan算法

2017-09-13 14:41 197 查看

 

1. 算法思想

如果两个顶点可以相互通达,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量(strongly
connected components)。下图中,子图{1,2,3,4}为一个强连通分量,因为顶点1,2,3,4两两可达。{5},{6}也分别是两个强连通分量。Tarjan算法是用来求有向图的强连通分量的。求有向图的强连通分量的Tarjan算法是以其发明者Robert Tarjan命名的。Robert
Tarjan还发明了求双连通分量的Tarjan算法。Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。定义DFN(u)为节点u搜索的次序编号(时间戳),Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号。当DFN(u)=Low(u)时,以u为根的搜索子树上所有节点是一个强连通分量。(很容易理解,定义DFN(u)为节点u搜索的次序编号(时间戳),
Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号。DFN定义的是按照顺序可以到达的,例如v0是1 ,v1是2, v0可以到达v2。LOW定义的是u可以到达的子树,例如v1在栈中的子树可以到达的次序1,那么v2肯定可以到达v1。所以v1和v2是强连通。如果v0和v1在栈内之间还有v00,v11那么v0,v00,v11,v1之间也是强连通的)。

2. 实例

从节点1开始DFS,把遍历到的节点加入栈中。搜索到节点u=6时,DFN[6]=LOW[6],找到了一个强连通分量。退栈到u=v为止,{6}为一个强连通分量。





返回节点5,发现DFN[5]=LOW[5],退栈后{5}为一个强连通分量





返回节点3,继续搜索到节点4,把4加入堆栈。发现节点4向节点1有后向边,节点1还在栈中,所以LOW[4]=1。节点6已经出栈,(4,6)是横叉边,返回3,(3,4)为树枝边,所以LOW[3]=LOW[4]=1。





继续回到节点1,最后访问节点2。访问边(2,4),4还在栈中,所以LOW[2]=DFN[4]=5。返回1后,发现DFN[1]=LOW[1],把栈中节点全部取出,组成一个连通分量{1,3,4,2}。





可以看出,采用的是深度优先的遍历,并且呢又给每个阶段增加了两个标记,判断是否是强连通。

3. 代码

4. #define M 5010//题目中可能的最大点数

5. int STACK[M],top=0;//Tarjan算法中的栈

6. bool InStack[M];//检查是否在栈中

7. int DFN[M];//深度优先搜索访问次序

8.

9. int Low[M];//能追溯到的最早的次序

10. int ComponentNumber=0;//有向图强连通分量个数

11. int Index=0;//索引号

12. vector<int> Edge[M];//邻接表表示

13. vector<int> Component[M];//获得强连通分量结果

14. int InComponent[M];//记录每个点在第几号强连通分量里

15. int ComponentDegree[M];//记录每个强连通分量的度

16.

17. void Tarjan(int i) 

18. { 

19. int j; 

20.     DFN[i]=Low[i]=Index++; 

21.     InStack[i]=true;STACK[++top]=i; 

22. for (int e=0;e<Edge[i].size();e++) 

23.     { 

24.         j=Edge[i][e]; 

25. if (DFN[j]==-1) 

26.         { 

27.             Tarjan(j); 

28.             Low[i]=min(Low[i],Low[j]); 

29.         } 

30. else

31. if (InStack[j]) Low[i]=min(Low[i],DFN[j]); 

32.     } 

33. if (DFN[i]==Low[i]) 

34.     { 

35.         ComponentNumber++; 

36. do

37.             j=STACK[top--]; 

38.             InStack[j]=false

39.             Component[ComponentNumber]. 

40.             push_back(j); 

41.             InComponent[j]=ComponentNumber; 

42.         } 

43. while (j!=i); 

44.     } 

45. } 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息