算法进阶强连通分量

树上跑一边DFS的代码很简单吧,图上的DFS与其相差无几。区别在于图上的DFS要记录每一个点是否被遍历过,如果已经被遍历过了,则跳过该点继续DFS;此外这个图有可能是个不完全连通,所以要确保每个点都被遍历到。

由此我们就知道一些有用的东西了,比如图中各点的DFS序,或者按照DFS序建一棵树:DFS生成树。

如上图,这就是一个在有向图中的一棵DFS生成树的例子。可以看见,在图中除了黑色的构成树的实边以外,还有一些虚边,它们不存在与生成树中,但却在原图中存在。对于这些边,我们可以给它们分别命名:

如果一个有向图中每一个点都能相互到达,则称该图为强连通图。一个图的极大子图如果是强连通图,则这个子图为该图的一个强连通分量。

在有向图中求强连通分量最经典的算法就是Tarjan算法了。Tarjan算法的基本思路就是在DFS整个图的同时为每个节点保存两个信息:

其实就是DFS序。

从该节点的子树出发,经过一条B边或C边可以到达的DFS序最小的在栈中的DFS序。

用这两个信息,就可以在DFS的同时找环了,而根据强连通分量的定义易知:一个环一定是一个连通分量。

所以为了方便维护这两个信息,我们引入一个栈,对于遍历到的一个点u,栈中保存已遍历过的,能通过某条路径到达u的节点。以此来将一个强连通分量里的可能点囊括到一起。

并且我们还需要一个bool数组来记录一个点是否在栈中。

Tarjan算法的关键就在于low,所以在DFS的过程中我们主要针对对low数组的更新来进行说明。当DFS遍历到一个点u时,对于其接下来将要遍历的节点v与二者之间的边e,分三种情况考虑:

语言无力,多说无用,不如直接上伪代码:

另外,如果一个点的所有子树都遍历完了,判断一下其DFS序与low的值的大小,如果发现其DFS序与low值相等,说明这个点是一个强连通分量的“根”,于是不断弹栈,直到将这个点也弹出来,这之前弹出的所有点都与其在同一个强连通分量中。

对于其正确性,不妨这样想:对于每一个强连通分量,有且仅有一个节点的DFS序与low值相等,且该节点一定是在DFS过程中第一个被遍历到的。因此其DFS序最小,所以更新low时不会被其下方的节点所影响。

而栈中在其之上的所有节点就是它能到达的所有节点,这也就说明其能到达的所有节点无法再到达在其之上的任何一个节点,这在代码中表现为low值比其大,不可能比其小,因为这样会在DFS过程中使其更新low值。以上,证毕。

那么说了这么多,强连通有什么用呢?想一想,一个强连通分量中的所有点都可以相互到达,那么不计较经过边数的话,如果一个节点可以到达强连通的其中一个点,那么必然也可以到达强连通的其它点。所以我们可以将一整个强连通分量坍缩成一个点,由此对图中每个强连通分量都进行缩点操作,就可以将一个有向图变成DAG(有向无环图)来解决问题了。这就是缩点。

如果原图是连通图,那么缩点之后就会变成一棵树。

每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜欢B,B喜欢C,那么A也喜欢C。牛栏里共有N头奶牛,给定一些奶牛之间的爱慕关系,请你算出有多少头奶牛可以当明星。

强连通版子题。不妨这么想:每头奶牛视作一个点,爱慕关系为有向边,则我们可以建一个图。而图中每个强连通分量中的每个点都可以相互到达,即相互爱慕,那么我们就可以将其视作一个点。

对每一个强连通分量,记录其中总点数。缩点完成后再遍历一次新的树,找到叶子节点。因为非叶子节点的子节点无法再到达它,即无法被子节点“爱慕”,只有叶子节点可能被所有点到达。

但还需要再考虑一件事,如果有多个叶子节点,那么这些叶子节点一定不可能互相到达,所以一定没有符合条件的奶牛。只有在只有一个叶子节点时,才输出该叶子节点中包含的点数。

以下为代码:

一个有向连通图中,燃烧每个点都需要一定费用。如果从某点出发能从一条路径回到该点,那么燃烧这条路径上所有点的总费用就等于这个点所需的费用。现在想燃烧所有的点,每个点可以重复经过。

虽然题面让人看得感同身受,但题目还是很简单的。首先求出强连通分量,然后记录下每个强连通分量中的最小值的点的点数,根据乘法原理,将这些数量相乘就是总方案数。别忘了边乘边模。

这题将缩点和最短路结合了,需要在scc上跑最短路。

这两题就当作思考题吧,都是强连通必刷题。

除Tarjan算法以外,还有几种求强连通分量的算法,如Kosaraju算法、Garbow算法等。想了解的可以去OIwiki自行查看。

THE END
1.八叉树算法原理八叉树算法原理 八叉树算法是一种用于描述三维空间的树状数据结构,主要用于空间划分和最近邻搜索。其原理是将一个立方体分割为八个小立方体,然后递归地分割小立方体,每个节点表示一个正方体的体积元素,每个节点有八个子节点,将八个子节点所表示的体积元素加在一起就等于父节点的体积。 在实际应用中,八叉树主要用于https://wenku.baidu.com/view/1f4557aaac45b307e87101f69e3143323968f5e9.html
2.游戏嘲管理的八叉树算法是怎样的?简单来说,八叉树的空间划分方式是,把一个立方体分割为八个小立法体,然后递归地分割小立方体。 相似地,四叉树把一个正方形空间分割成四个小正方形。由于三维空间较难理解,之后本答案主要以四叉树作图示解释。 四/八叉树有多种变种,先谈一个简化的情况,就是假设所有物体是一个点,这样比较容易理解。 https://www.jianshu.com/p/07a927e41cd5
3.基于多约束八叉树和多重特征的点云配准算法针对三维点云配准的优化目标,本文在深入学习三维点云配准算法、三维点云分割算法、曲面拟合算法的基础上,提出了一种多约束八叉树分阶拟合结合多重特征匹配的点云配准算法。首先增加多约束改进自适应八叉树以降低分割子域的曲面复杂度,接着根据分割特点选取分阶移动最小二乘(Moving Least Squares,MLS)拟合策略降低拟合https://cdmd.cnki.com.cn/Article/CDMD-10112-1019872455.htm
4.PCL——(6)八叉树Octreemb5ff409fbbe221的技术博客三、点云八叉树应用算法: 搜索操作(邻域、半径、体素搜索) 降采样(体素网格/体素质心滤波器) 点云压缩 空间变化检测 空间点密度分析 占用检查/占位地图 碰撞检测 点云合并 3.1 Octree用于点云压缩 在下面,我们将解释如何有效地压缩单点云和点云流。在这个例子中,我们使用OpenNIGrabber捕捉点云,并使用PCL点云压缩https://blog.51cto.com/u_15076209/4402357
5.点云数据压缩技术:八叉树方法详解PCL本文将详细介绍一种常用的点云数据压缩方法——八叉树。 一、八叉树概述 八叉树是一种基于空间划分的数据结构,它将三维空间递归地划分为八个子空间,每个子空间都包含该空间的一部分点云数据。在点云数据压缩中,八叉树可以通过不断地对空间进行划分和合并来实现压缩和重建。 二、八叉树点云压缩算法 下面我们将https://download.csdn.net/blog/column/12410899/132350184
6.大话数据结构(算法)一个算法,就是一个有穷规则的集合,其中规则规定了一个解决某一特定类型的问题的运算序列;此外,一个算法有五个重要的特性 有穷性 指算法再执行有限的步骤之后,自动结束而不会出现无限循环,并且每一个步骤再可接受的时间内完成。 确定性 算法的每一个步骤,必须是确切定义的。 可行性 算法的每一步都必须是可行的https://zhuanlan.zhihu.com/p/541522249
7.八叉树索引(精选七篇)通过对经典八叉树算法分析可知, 如果将经典八叉树数据结构直接应用于海量点云数据的管理, 其各节点在存储结构上存在冗余, 比如, 为提高检索速度, 相邻指针和父指针会被存储在节点之间, 但是相应的内存空间会增大。如图1.1 所示, 指向父节点的指针我们在这里使用m_parent命名, 相应的, 定义孩子节点指针为m_child,https://www.360wenmi.com/f/cnkey1wp269n.html
8.重构网格修改器—BlenderManual八叉树算法深度 设置输出的分辨率。低值将产生相对于输入而言较大的面,较高的值将产生更密集的面。 缩放 结果还可以通过设置缩放作进一步地调整,较低的值有效地降低输出分辨率。 平滑着色 输出面用光滑着色,而不是平坦着色。输入面的光滑/平坦着色不被保留。 移除分离的块 过滤掉输出中不连接的小块。 输入网格的https://docs.blender.org/manual/zh-hans/2.83/modeling/modifiers/generate/remesh.html
9.三维复杂无粘流场的自适应八叉树结构直角网格算法模拟三维复杂无粘流场的自适应八叉树结构直角网格算法模拟 NUMERICAL SIMULATION FOR 3-D COMPLEX INVISCID FLOW FIELD WITH ADAPTIVE OCTREE CARTESIAN GRIDS 董程栋 航空学报 . 2000, (6): 504 -507 .https://hkxb.buaa.edu.cn/CN/lexeme/showArticleByLexeme.do?articleID=11253
10.foroctreevolumerenderingGPU加速的八叉树体绘制算法We presented a novel approach for empty space skipping for object-order volume rendering. A two-staged space skipping was introduced: the first stage applied bricking on a regular grid, and the second stage used octree to reach a finer granularity. The approach further took into account that https://www.oalib.com/paper/1627715
11.PCL中八叉树理论腾讯云开发者社区八叉树和k-d树比较 八叉树算法的算法实现简单,但大数据量点云数据下,比较困难的是最小粒度(叶节点)的确定,粒度较大时,有的节点数据量可能仍比较大,后续查询效率仍比较低,反之,粒度较小,八叉树的深度增加,需要的内存空间也比较大(每个非叶子节点需要八个指针),效率也降低。而等分的划分依据,使得在数据重心有https://cloud.tencent.com/developer/article/1475985
12.java简单实现八叉树图像处理代码示例java这个算法就是我最后选用的算法,它的主要思想就是把图像的RGB颜色值转成二进制分布到八叉树中,例如:(173,234,144) 转成二进制就是(10101101,11101010,10010000),将R,G,B的第一位取出来组成(111),作为root节点的子节点,其中111作为root子节点数组的索引,以此类推,一直到最后一位,然后在叶子节点上存放这个颜色https://www.jb51.net/article/131194.htm
13.三叉树算法,ternarytreealgorithm,音标,读音,翻译,英文例句建立了具有多对独立杂合基因的自交群体的基因型熵的逐代演变数学模型,给出每一世代中各个基因型所占的比例的三叉树算法。 2) octree quantization 八叉树算法 例句>> 3) quadtree arithmetic 四叉树算法 例句>> 4) Quintuple tree method 五叉树算法 http://www.dictall.com/indu/213/2129514989B.htm
14.在大数据环境下如何优化DBSCAN算法问答八叉树:结合八叉树与DBSCAN算法,可以大幅提升聚类速度,特别是在处理大规模点云数据时。 网格单元:采用网格单元划分数据空间,减少点对点的距离计算,从而提高算法效率。 算法改进 雪融算法:通过引入雪融算法对DBSCAN进行参数优化和性能提升,实现更高效的数据聚类分析。 优化参数:通过调整参数,如邻域半径ε和最小邻域数Minhttps://www.yisu.com/ask/13475293.html
15.一种林火预报与火势蔓延计算方法11.在林火蔓延模型上从8个方向对林火进行模拟,避免了先前只通过五个方向速度对林火进行模拟的不完善,其动态性强,依赖参数少,获取方便,提高了模拟的精度和效率,因而可准确定位林火蔓延后各方向的位置,且模型具有简单易行的特点;根据所提出的平面八叉树算法可直接模拟小班林火蔓延的过程。 https://www.xjishu.com/zhuanli/55/202111319207.html
16.一种三维点云自适应隐式曲面重构方法AET摘要: 基于自适应八叉树和改进的差分进化算法,提出了一种对三维点云数据进行隐式曲面重构的方法。首先对原始点云进行八叉树自适应分割;然后采用改进的径向基元球模型建立局部隐式曲面函数,并运用差分进化算法自适应求解径向基中心、影响半径和形状参数;最后采用改进的对数指数加权拼接算法对局部曲面进行光滑拼接,并采用http://www.chinaaet.com/article/3000104195