zoukankan      html  css  js  c++  java
  • 拓扑排序

    在图论中,拓扑排序(Topological Sorting)是一个有向无环图(DAG, Directed Acyclic Graph)的所有顶点的线性序列。且该序列必须满足下面两个条件:

    每个顶点出现且只出现一次。
    若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面。
    有向无环图(DAG)才有拓扑排序,非DAG图没有拓扑排序一说。

    从 DAG 图中选择一个 没有前驱(即入度为0)的顶点并输出。
    从图中删除该顶点和所有以它为起点的有向边。
    重复 1 和 2 直到当前的 DAG 图为空或当前图中不存在无前驱的顶点为止。后一种情况说明有向图中必然存在环。

    通常,一个有向无环图可以有一个或多个拓扑排序序列。

    拓扑排序的三种方法:

    1.无前趋的的顶点优先拓扑排序

        思路:在有向图建立完成之后,维护两个点集,一个是当前出度为0的点集,记为①,另一个是出度不为0 的点集,记为②,以及一个记录各个点出度的数组。首先遍历一遍图的全部边,初始化所有点的出度,然后出度为0的点依次 入①,然后将①中的点分别出列,每次出列都需要更新各个点的出度,即把所有跟出列的点邻接的点出度-1(有多条边,则相应减掉边数,一般简单图不会有多重边),直至①变成空集。这个时候,如果②也变成了空集,证明排序成功,否则,原图不存在拓扑排序(图中有环)。最终的排序结果就是从①中出列的点的逆序。

    2.无后继的的顶点优先拓扑排序

      思路:跟1的方法类似,不过这次是维护根据点的入度进行统计。在有向图建立完成之后,维护两个点集,一个是当前入度为0的点集,记为①,另一个是入度不为0 的点集,记为②,以及一个记录各个点入度的数组。首先遍历一遍图的全部边,初始化所有点的入度,然后入度为0的点依次 入①,然后将①中的点分别出列,每次出列都需要更新各个点的入度,即把所有跟出列的点邻接的点入度-1(有多条边,则相应减掉边数,一般简单图不会有多重边),直至①变成空集。这个时候,如果②也变成了空集,证明排序成功,否则,原图不存在拓扑排序(图中有环)。最终的排序结果就是从①中出列的点的顺序。

    3.基于DFS递归的拓扑排序

      思路:从图的起点开始进行深度优先搜索,在搜索过程中,把没有后继(相当于出度为0)的点出列(这个过程中,已经出列的点不算是它的前继点,相当于删除了该点),点的出列顺序就是拓扑排序结果的逆序。

    下面分析一些hdu上的题目来考察这三个方法的异同。

    1.前两种方法本质上是一样的,只不过一个得到的是顺序,一个是逆序,这就根据情况和喜好进行判断,对于关系(a,b)我们直观上认为在图中是这样的 a -> b, 然而,在某些题目中(a,b)的意义可能是 a>b,这就不大符合我们的直观理解(一般认为图的上端好,大……),不过这都不影响排序结果,各求所需就好。

    2.未经优化的DFS拓扑排序,在图存在环的时候会进入死循环,因此,要注意确保图没有环,或者最好进行优化再使用。

    3.维护出度为0以及DFS拓扑得到的结果是逆序!

    4.拓扑排序结果不一定唯一,注意题目要求。

    5.DFS拓扑需要知道图的起点,否则不能深搜整个图,也就没有得到完整的拓扑排序结果。

    6.在维护点集的拓扑中,加入当前出度(入度)为0的点大于1个,则得到的拓扑排序结果不唯一

  • 相关阅读:
    hdu 3714
    sql 函数 DATEADD 使用
    mvc的IIS 配置问题 runAllManagedModulesForAllRequests 与 HtmlFileHandler
    移动端日历控件 mobiscroll 的简单使用、参数设置
    sql中判断是否存在某个对象
    SQLServer中的变量:局部变量,全局变量
    键盘对照表
    [PyQt]在Windows系统中安装Eric6
    [Python]使用QRCode生成彩色二维码
    [PyQt]PyQt5连接SQL Server数据库,并读取所有数据库名称
  • 原文地址:https://www.cnblogs.com/lunatic-talent/p/12798762.html
Copyright © 2011-2022 走看看