- 1、本文档共4页,可阅读全部内容。
- 2、有哪些信誉好的足球投注网站(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
我的Tarjan总结
Contents:?一、连通图和连通分量?二、强连通图和强连通分量三、Tarjan算法思想首先,说一下基础概念。一、连通图和连通分量1.顶点间的连通性 在无向图G中,若从顶点vi到顶点vj有路径 当然从vj到vi也一定有路径 ,则称vi和vj是连通的。2.连通图 若V G 中任意两个不同的顶点vi和vj都连通 即有路径 ,则称G为连通图 Con-nected Graph 。 3.连通分量 无向图G的极大连通子图称为G的连通分量 Connected Component 。??注意: 任何连通图的连通分量只有一个,即是其自身 非连通的无向图有多个连通分量。二、强连通图和强连通分量1.强连通图 有向图G中,若对于V G 中任意两个不同的顶点vi和vj,都存在从vi到vj以及从vj到vi的路径,则称G是强连通图。2.强连通分量 有向图的极大强连通子图称为G的强连通分量。注意: 强连通图只有一个强连通分量,即是其自身。 非强连通的有向图有多个强连分量。下面三、Time 0;
dfs v : low[v] dfn[v] time ++; stack.push v ;
扫描v能直接到达的顶点k,如果k没被访问过那么先dfs k ,low[v] min low[v],low[k] ;如果k已经被访问了,则low[v] min low[v],dfn[k] (就是这里使low[v]不一定最小,但不会影响这里low[v] 会小于dfn[v])。
扫描完所有k后,若low[v] dfn[v],则stack里v以上的所有元素出栈,则出栈的就是极大强连通分量。
四、Tarjan算法证明:
1. 在栈里,当dfs遍历到v,而且已经遍历完v所能直接到达的顶点时,low[v] dfn[v]时,v一定能到达栈里v上面的顶点: 因为当dfs遍历到v,而且已经dfs递归调用完v所能直接到达的顶点时(假设上面没有low dfn),这时如果发现low[v] dfn[v],栈上面的顶点一定是刚才从顶点v递归调用时进栈的,所以v一定能够到达那些顶点。
2 .dfs遍历时,如果已经遍历完v所能直接到达的顶点而low[v] dfn[v],我们知道v一定能到达栈里v上面的顶点,这些顶点的low一定小于 自己的dfn,不然就会出栈了,也不会小于dfn[v],不然low [v]一定小于dfn[v],所以栈里v以其v以上的顶点组成的子图是一个强连通分量,如果它不是极大强连通分量的话low[v]也一定小于dfn[v](这里不再详细说),所以栈里v以其v以上的顶点组成的子图是一个极大强连通分量。
五、Tarjan算法的时间复杂度分析
因为所有的点都刚好进过一次栈,所有的边都访问的过一次,所以时间复杂度为O(n+m)。
六、Tarjan算法参考代码
#include
#include
#include
#define MAX 4001
using namespace std;
int Stop;//栈中的元素个数
int cnt;//记录连通分量的个数
int visitNum;//记录遍历的步数
int DFN[MAX]; //记录节点u第一次被访问时的步数
int LOW[MAX]; //记录与节点u和u的子树节点中最早的步数
bool instack[MAX];//记录节点u是否在栈中
int Stap[MAX];//栈
int Belong[MAX];//记录每个节点属于的强连通分量编号
int N;//节点个数
vector tree[MAX];
void tarjan int i int j;
DFN[i] LOW[i] ++visitNum;
instack[i] true;
Stap[++Stop] i;//将当前节点压入栈中
for unsigned k 0;k tree[i].size ;k++ j tree[i][k];
if !DFN[j] //j还没有被访问过 tarjan j ; //父节点是子节点的子节点 if LOW[j] LOW[i] LOW[i] LOW[j]; //与j相连,但是j已经被访问过,且还在栈中
//用子树节点更新节点第一次出现的时间
else if instack[j] DFN[j] LOW[i] LOW[i] DFN[j]; //节点i是强连通分量的根
if DFN[i] LOW[i] cnt++;
//输出找到的强连通分量
cout 连通分量 cnt : ;
//退栈,直至找到根为止
do j Stap[Stop--]; instack[j] false; cout j ; Belong[j]
文档评论(0)