Algorithm 在有向图和无向图上使用单一算法来检测循环?

Algorithm 在有向图和无向图上使用单一算法来检测循环?,algorithm,recursion,graph,depth-first-search,directed-graph,Algorithm,Recursion,Graph,Depth First Search,Directed Graph,我一直在尝试实现一种算法来检测有向和无向图中的循环(可能有多少个)。也就是说,代码应该同时适用于有向图和无向图 在各种帖子中,大多数推荐使用DFS或拓扑排序。但在很大程度上,一切都是针对无向图的 描述一种循环检测方法。据我所知,这适用于有向图 具有无向图中循环检测的代码。但我不明白它是如何忽略后缘的。也就是说,它必须忽略任何有两个节点的循环,比如说D到C和C到D。 这意味着它必须在DFS递归时记住它的父级。但代码似乎没有考虑到这一点 欢迎提出任何建议 首先,一些重要方面: -检测周期通常比计算周

我一直在尝试实现一种算法来检测
有向和无向图中的循环(可能有多少个)。也就是说,代码应该同时适用于有向图和无向图

在各种帖子中,大多数推荐使用
DFS或拓扑排序。但在很大程度上,一切都是针对无向图的

描述一种循环检测方法。据我所知,这适用于有向图

具有无向图中循环检测的代码。但我不明白它是如何忽略后缘的。也就是说,它必须忽略任何有两个节点的循环,比如说D到C和C到D。 这意味着它必须在DFS递归时记住它的父级。但代码似乎没有考虑到这一点

欢迎提出任何建议


首先,一些重要方面: -检测周期通常比计算周期容易(因为您可以在另一个周期内拥有周期) -事实上,对于有向图和无向图,算法可能非常不同(通常,对于无向图,算法更有效)

其次,我的2美分通用算法(有向图的循环计数)将稍微修改:

for(int k=0;k
上面的代码段假设A是图形的邻接矩阵,n是节点数。复杂性显然是O(n^3)

它将修改邻接矩阵,以在每个位置(i,j)包含从i开始并以j结束的路径数。换句话说,如果您对以节点x开始的循环数感兴趣,只需读取A[x][x](矩阵主对角线的对应数)

这里剩下的唯一问题是您是否对全局循环计数感兴趣。由于我没有一个正确的解决方案的证明(并且没有时间验证),我不会发布任何细节(对不起)


PS:对于循环检测(仅限),有更快的选项可用:

  • 在无向图(最简单的情况)中,尝试查看Union find问题()。这是我所知道的最快的非平凡图算法之一(如果我没记错的话,所有优化几乎都是线性的)

  • 在有向图中,我将使用DFS,正如您所提到的。如果在“dfs”函数中为“if(!marked[v])放置一个else(如:else“找到一个循环”),那么您提到的第二个链接可以正常工作


首先,一些重要方面: -检测周期通常比计算周期容易(因为您可以在另一个周期内拥有周期) -事实上,对于有向图和无向图,算法可能非常不同(通常,对于无向图,算法更有效)

其次,我的2美分通用算法(有向图的循环计数)将稍微修改:

for(int k=0;k
上面的代码段假设A是图形的邻接矩阵,n是节点数。复杂性显然是O(n^3)

它将修改邻接矩阵,以在每个位置(i,j)包含从i开始并以j结束的路径数。换句话说,如果您对以节点x开始的循环数感兴趣,只需读取A[x][x](矩阵主对角线的对应数)

这里剩下的唯一问题是您是否对全局循环计数感兴趣。由于我没有一个正确的解决方案的证明(并且没有时间验证),我不会发布任何细节(对不起)


PS:对于循环检测(仅限),有更快的选项可用:

  • 在无向图(最简单的情况)中,尝试查看Union find问题()。这是我所知道的最快的非平凡图算法之一(如果我没记错的话,所有优化几乎都是线性的)

  • 在有向图中,我将使用DFS,正如您所提到的。如果在“dfs”函数中为“if(!marked[v])放置一个else(如:else“找到一个循环”),那么您提到的第二个链接可以正常工作


第二个链接是关于检测连接的组件,而不是关于循环。连接组件本质上不是一个循环吗?循环是
k
顶点的子图,其中有
k
边将
k
顶点连接到单个循环中。连通分量是连接的
k
顶点的诱导子图。在图形示例中,只有一个连接的组件(整个图形),并且有三个循环:
A-B-E-A
A-B-D-A
A-E-B-D-A
。第二个链接是关于检测连接的组件,不是关于循环。连接组件本质上不是循环吗?循环是
k
顶点的子图,其中有
k
边将
k
顶点连接到单个循环中。连通分量是连接的
k
顶点的诱导子图。在图形示例中,只有一个连接的组件(整个图形),并且有三个循环:
A-B-E-A
A-B-D-A
A-E-B-D-A
for (int k = 0; k < n; k++) {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            A[i][j] += A[i][k] * A[k][j];
        }
    }
}