• 弗洛伊德判环,找环起点,找环长的算法


    弗洛伊德判环,找环起点,找环长的算法

    有这样一种问题……

    对于一种特殊但是常见的有向图:每个点都有一条出边(出度为1)。我们想要掌握它的结构,怎么办呢?很容易发现,这样的图一定是这样的:
    像不像一个八爪鱼?
    而我们单看某一个起点出发能到达的子图时,我们会发现这是一个‘ρ’形的图;即“一条链”接上“一个环”的形状。
    当我们想要描述这个‘ρ’形图的结构时,自然便会引入三个参数:“环长”,“链长”,“链末端/环起点”。
    如果空间足够我们糟蹋,那开个数组存储每个点是否被访问过,或者深度之类的信息,自然很好处理出这三个参数的值。但是能这样做的前提有二:一、点的数目不会大到我们的空间承受不了的程度(因为经过的点都必须记录下它的信息);二、点的编号映射到数组的成本能够承受(具体一点比如说点的编号不大)。
    当我们在只有“比较两点是否是同一点”和“询问一个点的出边”这两种操作被允许的情景下,如何找到刚刚我们想求的参数呢?

    弗洛伊德判环

    设入环前,连的长度为(m),环长为(n)
    只用一个指针(指用来指示点编号的变量),能记录的信息很有限。
    那么考虑两个指针,以不同的速度从起点出发:一个指针(记为tortoise,慢指针)每次经过一个出边指向下一个点;而另一个指针(记为hare,快指针)每次经过两个出边指向下下个点。
    这样一来,当慢指针从起点出发,经过(m)条边,刚刚进入环时;快指针已经经过了(2m)条边;
    记环起点为(0)点,(0)点的出边到达的点为(1)点,接下来(2)点,(3)点,一直到(n-1)点,以此类推……
    那么慢指针这时到达了0点,而快指针则到达了((m mod n))点,而快指针到慢指针的距离为((-m mod n));因为接下来慢指针每走一步,两个指针之间都会缩短距离(1),所以当快慢指针相遇时指针的位置正好会在((-mmod n))
    那么必然,慢指针再走m步,它便会回到0点;因为((m+(-m)) mod n equiv 0)
    因此,我们只需要在两者相遇时把快指针放回起点,并把它的速度调整到和慢指针一致(都是每次经过一条出边)。那么m次之后,他们必然会相遇于环起点。(即(0)点)
    记录期间指针的移动次数,便可以计算出m
    这时候,一个指针不动,另一个指针绕环一周,通过记录相遇步数,便可以得出环的长度。

  • 相关阅读:
    Google Map API使用详解(三)——Google Map基本常识(上)
    Google Map API使用详解(十)——使用JavaScript创建地图详解(上)
    sethc.exe
    taobao_java
    "void __cdecl operator delete[](void *)" (??_V@YAXPAX@Z) 已经在 LIBCMTD.lib(delete2.obj) 中定义 错误
    some Content
    变参 C++ 转帖
    阅读大型程序你得到什么
    一些模块
    a common jsp
  • 原文地址:https://www.cnblogs.com/JeffLee-AuB/p/15106702.html
Copyright © 2020-2023  润新知