如何仅使用邻接表查找无向图中存在的循环(顶点也没有)?

时间:2019-07-12 15:58:47

标签: c++ algorithm graph-theory adjacency-matrix graph-traversal

如果您只有一个邻接矩阵,如何找到无向图中的循环在哪里?

3 个答案:

答案 0 :(得分:1)

要在无向图中查找循环,您需要在该图中运行深度优先搜索(DFS)。如果您的图形表示为邻接矩阵,则其运行时间为Θ(V + E),其中V是顶点数,E是边数。运行DFS时,您希望将遍历的每个边缘分类为树边缘后边缘。如果在处理(u,v)之前未看到v,则顶点u和v之间的边(表示为(u,v))是树的边缘。如果在处理(u,v)之前已经发现v,则(u,v)是后端。发现后边缘表示图形中存在一个循环,因为存在一条路径,该路径从一个边开始从顶点出发,然后从另一边回到同一顶点。对所有边缘进行分类后,任何后边缘(u,v)都会与树边缘形成一个循环,从而形成从u到v的路径。

答案 1 :(得分:0)

For every vertex:
   If the vertex u is unvisited so far:
        Previous vertex  = u.
        Start a depth first search from u.


Depth_first_search(vertex u, previous vertex p):
    Mark vertex u as visited.
    For every neighbor of u say v:
        If vertex v is unvisited:
            Depth_first_search(v, u)
        If vertex v is visited and v != p:
            Cycle is present

以上是使用深度优先搜索来检测无向图中的循环的粗略算法。邻接表和邻接矩阵表示的算法相同。在Internet上进行简单的搜索即可为您提供所需的代码,但我要求您先自己尝试使用该代码。 作为练习,您也可以使用广度优先搜索来检测周期(如果存在)。

以上算法假定图形简单并且没有平行边。

答案 2 :(得分:0)

您可以找到我称之为“简单”循环的所有内容,如下所述。我所说的“简单”循环是不包含任何子循环的循环。如果包含“非简单”循环,则图可能无限多个。例如,考虑以下图形:

     (C)--(D)
      |   /
      |  /
      | /
(A)--(B)
  \   |
   \  |
    \ |
     (E)

“简单”周期是ABE和BCD。所有其他循环都包含这些完整循环之一。如果要包含“不完整”的循环,则可以按以下顺序获得无限多个循环:ABE,ABCDBE,ABCDBCDBE,…或AB(CDB)* E(从正则表达式中借用)。

要找到我描述的循环,请从图中的每个顶点进行深度优先搜索,以查找低于搜索根的层次遇到的初始节点。为了使循环保持“简单”,如果遇到已经见过的任何其他节点(除根以外),我们将停止沿路径搜索。在我们的示例图上,外观如下:

Depth-first search from A for A
DFS search to B, AB
 DFS search to C, ABC
  DFS search to D, ABCD
   DFS search to B; duplicate, skip;
   no other unvisited notes reachable, go up;
  no other unvisited nodes reachable, go up;
 DFS search to D, ABD
  DFS search to C, ABDC
   DFS search to B; duplicate; skip;
   no other unvisited nodes reachable, go up;
  no other unvisited nodes reachable, go up;
 DFS search to E, ABE
  DFS search to A; found target; register ABE;
  no other unvisited notes reachable, go up;
DFS search to E, AE
 DFS search to B, AEB
  DFS search to A; found target; register AEB;
  DFS search to C, AEBC
   DFS search to D, ABECD
    DFS search to B; duplicate; skip;
    no other unvisited nodes reachable; go up;
   no other unvisited nodes reachable; go up;
  no other unvisited nodes reachable; go up;
 no other unvisited nodes reachable; go up;
no other unvisited nodes reachable; go up;
(return)

如果我们对其余节点继续进行此操作,我相信我们会发现以下已注册的周期:

ABE, AEB
BAE, BEA, BCD, BDC
CDB, CBD
DBC, DCB
EBA, EAB

请注意,它们在旋转时可能等效,并且由于图形是无向的,因此它们在反转时也等效(即ABE和EBA是相同的循环)。为了解决这个问题,我建议首先将上面列出的每个循环转换为如下的“规范”表示形式:

  1. 旋转循环,以便最早的顶点排在第一位
  2. 反转循环然后旋转循环,以便最早的顶点排在第一位
  3. 选择最早的顶点作为标准周期

这是我们的情况:

Original    Rotated   Reversed    Reverse-Rotated    Chosen    Reason
ABE         ABE       EBA         AEB                ABE       ABE < AEB
AEB         AEB       BEA         ABE                ABE       ABE < AEB
BAE         AEB       EAB         ABE                ABE       ABE < AEB
BEA         ABE       AEB         AEB                ABE       ABE < AEB
BCD         BCD       DCB         BDC                BCD       BCD < BDC
BDC         BDC       CDB         BCD                BCD       BCD < BDC
CDB         BCD       BDC         BDC                BCD       BCD < BDC
CBD         BDC       DBC         BCD                BCD       BCD < BDC
DBC         BCD       CBD         BDC                BCD       BCD < BDC
DCB         BDC       BCD         BCD                BCD       BCD < BDC
EBA         AEB       ABE         ABE                ABE       ABE < AEB
EAB         ABE       BAE         AEB                ABE       ABE < AEB

我们发现选择了两个独特的周期:ABE和BCD。