Tarjan 算法
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Tarjan 算法,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2899字,纯文字阅读大概需要5分钟。
内容图文
![Tarjan 算法](/upload/InfoBanner/zyjiaocheng/1129/be6454cbd636461787c7dcca0b52bee9.jpg)
Tarjan算法
维基百科,自由的百科全书
Tarjan算法 (以发现者Robert Tarjan[1]命名)是一个在图中寻找强连通分量的算法。虽然发表时间更早,它仍可以被视为Kosaraju算法的一个改进。它的效率跟Gabow算法差不多。
概述
此算法以一个有向图作为输入,并按照所在的强连通分量给出其顶点集的一个划分。图中的每个结点只在一个强连通分量中出现,即使是在有些结点单独构成一个强连通分量的情况下(比如图中出现了树形结构或孤立结点)。
算法的基本思想如下:任选一结点开始进行深度优先搜索(若深度优先搜索结束后仍有未访问的结点,则再从中任选一点再次进行)。搜索过程中已访问的结点不再访问。搜索树的若干子树构成了图的强连通分量。
结点按照被访问的顺序存入栈中。从搜索树的子树返回至一个结点时,检查该结点是否是某一强连通分量的根结点(见下)并将其从栈中删除。如果某结点是强连通分量的根,则在它之前出栈且还不属于其他强连通分量的结点构成了该结点所在的强连通分量。
根结点的性质
算法的关键在于如何判定某结点是否是强连通分量的根。注意“强连通分量的根”这一说法仅针对此算法,事实上强连通分量是没有特定的“根”的。在这里根结点指深度优先搜索时强连通分量中首个被访问的结点。
为找到根结点,我们给每个结点v一个深度优先搜索标号v.index,表示它是第几个被访问的结点。此外,每个结点v还有一个值v.lowlink,表示从v出发经有向边可到达的所有结点中最小的index。显然v.lowlink总是不大于v.index,且当从v出发经有向边不能到达其他结点时,这两个值相等。v.lowlink在深度优先搜索的过程中求得,v是强连通分量的根当且仅当v.lowlink = v.index。
伪代码
algorithm tarjan isinput: 图 G = (V, E) output: 以所在的强连通分量划分的顶点集 index := 0 S := empty // 置栈为空for eachvinVdoif (v.index is undefined) strongconnect(v) end iffunction strongconnect(v) // 将未使用的最小index值作为结点v的indexv.index := indexv.lowlink := indexindex := index + 1 S.push(v) // 考虑v的后继结点for each (v, w) inEdoif (w.index is undefined) then// 后继结点w未访问,递归调用 strongconnect(w) v.lowlink := min(v.lowlink, w.lowlink) else if (w is in S) then// w已在栈S中,亦即在当前强连通分量中v.lowlink := min(v.lowlink, w.index) end if// 若v是根则出栈,并求得一个强连通分量if (v.lowlink = v.index) then start a new strongly connected component repeatw := S.pop() add w to current strongly connected component until (w = v) output the current strongly connected component end ifend function
变量index是深度优先搜索的结点计数器。S是栈,初始为空,用于存储已经访问但未被判定属于任一强连通分量的结点。注意这并非一个一般深度优先搜索的栈,结点不是在以它为根的子树搜索完成后出栈,而是在整个强连通分量被找到时。
最外层循环用于查找未访问的结点,以保证所有结点最终都会被访问。strongconnect进行一次深度优先搜索,并找到结点v的后继结点构成的子图中所有的强连通分量。
当一个结点完成递归时,若它的lowlink仍等于index,那么它就是强连通分量的根。算法将在此结点之后入栈(包含此结点)且仍在栈中的结点出栈,并作为一个强连通分量输出。
---摘自wiki。http://zh.wikipedia.org/wiki/Tarjan%E7%AE%97%E6%B3%95
打了一下
#include<stack> #include<isotream> #include<vector> #include<cstring> constint N=1000; usingnamespace std; int index[N],lowlink[N]; bool instack[N],isvisit[N]; vector<int>G[N]; staticint id=1; stack<int>sta; int V,E; void init(){ memset(instack,0,sizeof(instack)); memset(index,0,sizeof(index)); memset(lowlink,0,sizeof(lowlink)); memset(isvisit,0,sizeof(isvisit)); sta.clear(); } void DFS(int v){ index[v]=id++; lowlink[v]=index[v]; sta.push(v); instack[v]=true; for(int i=0;i<G[v].size();i++){ int w=G[v][i]; if(!isvisit[w]){ DFS(w); lowlink[v]=min(lowlink[v],lowlink[w]); } elseif(instack[w]){ lowlink[v]=min(lowlink[v],index[w]); } } if(lowlink[v]==index[v]){ int w; cout<<‘{‘<<‘‘; do{ w=sta.top();sta.pop(); instack[w]=false; cout<<w<<‘,‘; }while(w!=v); cout<<‘}‘<<endl; } } void Tarjan(){ for(int v=1;v<=V;v++){ if(!isvisit[v]){ isvisit[v]=1; DFS(v); } } }
参考byvoid博客https://www.byvoid.com/blog/scc-tarjan
原文:http://www.cnblogs.com/wanggp3/p/3619209.html
内容总结
以上是互联网集市为您收集整理的Tarjan 算法全部内容,希望文章能够帮你解决Tarjan 算法所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。