强连通分支桥和割点.PPTVIP

  1. 1、本文档共21页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  5. 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  6. 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  7. 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  8. 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
强连通分支桥和割点

有向图的强连通分支 本讲义部分内容引用北京大学信息学院实验班袁洋、陈科吉同学讲义,特此致谢 定 义 在有向图G中,如果任意两个不同的顶点相互可达,则称该有向图是强连通的。有向图G的极大强连通子图称为G的强连通分支。 转置图的定义:将有向图G中的每一条边反向形成的图称为G的转置GT。(注意到原图和GT的强连通分支是一样的) Korasaju算法 procedure Strongly_Connected_Components(G);  begin   1.深度优先遍历G,算出每个结点u的结束时间f[u],起点如何选择无所谓。 2.深度优先遍历G的转置图GT,选择遍历的起点时,按照结点的结束时间从大到小进行。遍历的过程中,一边遍历,一边给结点做分类标记,每找到一个新的起点,分类标记值就加1。   3. 第2步中产生的标记值相同的结点构成深度优先森林中的一棵树,也即一个强连通分量  end; 证明参考:/Algorithm/ShowArticle.asp?ArticleID=58 (a)为有向图G,其中的阴影部分是G的强连通分支,对每个顶点都标出了其发现时刻与完成时刻,黑色边为深度优先搜索的树 枝; (b)G的转置图GT 依次以b,c,g,h为起点做DFS, 得到4个强连通分量 算法复杂度分析 深度优先搜索的复杂度:Θ(V + E) 计算GT的复杂度:0或者Θ(V + E)(临接表) 所以总的复杂度为:Θ(V + E) 非常好的算法! Kosarajus algorithm 思考:Professor Deaver声称,用于强连通分支的算法可以这样简化,即在第二次深度优先搜索中使用原图(而不是其转置图),并按完成时间递增的顺序来扫描各个节点。这位教授的说法正确么? Tarjan 算法 Q:为什么要膜拜Tarjan? 1.DFS是Hopcroft和Tarjan提出的 2.今天介绍的求强连通分支的一个算法是Tarjan提出的,被称为Tarjan算法 3.Tarjan对DFS做了大量研究,包括离线的LCA算法和平面图判定算法都是使用了DFS的经典算法 4.Tarjan是大牛! 参考: /blog/scc-tarjan/ Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树。既然强连通分量是深搜树的一棵子树,要找到一个分量,只要找到树根( 连接不同分量的桥的前端顶点) ,然后取出其所属分量的顶点即可。 当深搜过程中遇到一个分量,首先发现的顶点v肯定是树根,由于分量是一棵子树,且分量间顶点可互达,那么其他顶点肯定能由v 发起的路径到达,那么其他节点都是v的子孙。 定义dfn数组,dfn[u] 表示u在深度优先遍历中的序号 我们定义 low 数组,low[v] 表示,从v出发经过v 的子孙形成的路径和一条回退边,能够到达的最浅层次的顶点的序号。注意这里到达的顶点必须是可用的,我们说当一个分量完成,其包括的顶点全部设置为不可用。其实如果边是一条不同子树之间的横跨边,它到达的顶点肯定是不可用的,因为那个点已经属于另一个分量。 参考:/lewutian/archive/2009/08/30/4499657.aspx 在dfs过程中,遇到新点令其dfn[u] = low[u] =当前遍历序号 . 回溯时,如果发现dfn[u] == low[u], 则u是分量子树的树根。 这是一个充要条件。 --: 如果u 是树根,且由于是强分量,其子孙都可达到u, 则子孙的low 都是u 的编号。则low[u] = dfn[u].??? --: 如果low[u] == dfn[u], 假设u不是树根,那么肯定有u的祖先是树根,那么low[u]肯定比当前值小,矛盾,因此u是树根。 如何取出分量? 我们遇到新顶点时将顶点入栈,在回溯时发现了根,且根是先被压入栈的,那么在根之后压入的顶点都是分量中的顶点,否则如果有顶点属于其他分量,就出现矛盾,因为在那个分量完成时,这个顶点已经弹出不可用了。 tarjan(u) { DFN[u]=Low[u]=++time // 为节点u设定次序编号和Low初值 Stack.push(u) // 将节点u压入栈中 for each (u, v) in E // 枚举每一条边 if (v is not visted) // 如果节点v未被访问过 tarjan(v) // 继续向下找 Low[u] = min(Low[u], Low[v]) else if (v in Stack )

文档评论(0)

2105194781 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档