图论基础算法

图论基础算法


图的拓扑排序

只有有向无环图才存在拓扑排序,拓扑排序满足一个条件:如果边 (u, v) 存在,那么在拓扑排序中 u 一定位于 v 的前面,这也间接的说明了为什么只有有向无环图才存在拓扑排序。

拓扑序列并不唯一

计算每一个点的入度,将入度为 0 的点追加到拓扑序列的末尾,并且将追加到序列末尾的点的出边删除,这样就会出现新的入度为 0 的点。
如果初始的时候不存在入度为 0 的点说明图中存在环。如果将能加入序列的点加入序列之后仍有点未加入序列,则也说明图中存在环


欧拉回路

欧拉回路指的是一条从起点出发再次回到起点的路径,因此具有欧拉回路的图一定是个有环图。我们可以使用深搜和回溯操作来找路径,这个一定是正确的但是由于具有很多环所以深搜的回溯次数非常多,不满足时间限制。

当深搜到无法继续向前扩展的时候说明这条路径一定与起点连接,而且剩余未选择的路径一定是环。如果我们回溯的话一定会在第一个出现分歧的地方选择其他路径,那么我们一定会走一个环之后又回到这个出现分歧的地方,然后继续按照第一次选择路径的方法走到起点。也就是说第一次选择路径的方法是正确的。我们只需要将其他的环加到这个路径中就行了。因此我们可以在回溯中讲回溯到的边添加到节点中,最后逆序输出即可。


次小生成树

定义: 设 G = (V , E) 是连通的无向图,T 是图 G 的一个最小生成树。如果有另一棵树T1,T1 ≠ T,满足不存在树 T’, T’ ≠ T ,w(T’) < w(T1) , 则称 T1 是图 G 的次小生成树

简单来说次小生成树就是一棵除最小生成树以外边权之和最小的生成树
(次小生成树的边权之和可以与最小生成树的边权之和相等)

显而易见的是我们可以首先枚举最小生成树上的边,然后将枚举到的边删除,然后再求最小生成树。由于去掉了一条最小生成树中的边,那么我们得到的一定是最小生成树
由于最小生成树有 n 个节点,因此存在 n - 1 条边,那么我们总共需要求 n 次最小生成树,复杂度较高不建议使用。

另一种求最小生成树的方法是首先求出最小生成树,然后枚举不在最小生成树中的边,将这个边添加到最小生成树中,一定会构成一个环。将除添加的这条边以外的最长边删除,也就是说第二长的边,就得到了相对添加的这条边的次小生成树。而需要删除的边我们可以通过预处理得到


Floyd算法

有很多人在初学 Floyd 算法的时候只是简单地背过了那几行代码,但是并没有真正了解 Floyd 的本质

Floyd 是一个已经压缩一维空间的动态规划算法,用 f[k][i][j] 表示只经过前 k 个点, 由点 i 到点 j 的最短路径长度。所以他的状态转移方程就是

f[k][i][j]=max(f[k][i][j],f[k1][i][k]+f[k1][k][j])

与背包问题类似,数组中的 k 是外层循环, 同样我们也可以压缩掉这一维,就形成了我们常见的 Floyd 算法。


LCA Tarjan 算法

Tarjan 求 LCA 是一个基于深搜的离线算法,需要在进行算法之前将所有的数据读入,算法思路如下:

为当前搜索节点 u 建立集合, 深搜它的每一个子树 v ,并将这些节点标记为以搜索,搜索完之后将这个子树与当前节点合并。当 u 的所有子树都已经搜索完毕,处理与 u 节点有关的查询。如果查询的另一个节点 s 已经被标记过,则说明这个查询的结果是 s 当前所处于的集合。

更加详细的Tarjan算法请参考这里

发布了33 篇原创文章 · 获赞 16 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/Fine_rose/article/details/76946292