简体   繁体   English

了解Skiena的算法以检测图中的循环

[英]Understanding Skiena's algorithm to detect cycles in a graph

I'm having trouble understanding everything in Skeina's algorithm to detect cycles in a graph whether directed or undirected 我无法理解Skeina算法中的所有内容,无论是有向还是无向,都能检测图中的周期

void process_edge(int v, int y) {
    // if parent[v] == y it means we're visitng the same edge since this is unweighted?
    // y must be discovered otherwise this is the first I'm seeing it?
    if (discovered[y] && parent[v] != y) {
        printf("\nfound a back edge (%d %d) \n", v, y);
    }
}

void DFSRecursive(graph *g, int v) {
    discovered[v] = true;

    edge *e = g->edges[v];
    while (e != NULL) {
        int y = e->y;
        if (discovered[y] == false) {
            parent[y] = v;
            DFSRecursive(g, y);
        } else if (!processed[y] || g->directed) { // can't be processed and yet has an unvisited kid!?
            process_edge(v, y, data);
        }
        e = e->next;
    }

    processed[v] = true;
}
  1. Why are we checking !processed[y]? 我们为什么要检查!处理[y]? If we see a neighbor y and it was discovered already (first if condition), how would it be possible that y has been processed? 如果我们看到一个邻居y并且它已经被发现(首先是条件),y怎么可能被处理? given that v is a neighbor and we discovered it just now? 鉴于v是邻居,我们刚刚发现它?
  2. I was confused with the check for parent[v] !== y but I guess it makes sense in the unweighted graph case, if we have a graph with just two nodes, both nodes have each other in their adjacency so this is not a cycle. 我对父[V]!== y的检查感到困惑,但我想在未加权的图形情况下它是有意义的,如果我们有一个只有两个节点的图形,两个节点彼此相邻,所以这不是一个周期。 I'm not clear though on why it would make sense in the directed case because 1->2 and 2->1 is considered a cycle, right? 我不清楚为什么它会在定向案例中有意义,因为1-> 2和2-> 1被认为是一个循环,对吧?
  3. I don't have problems with the third condition discovered[y] in the process edge method because if it undiscovered, it would mean this is the first time we are seeing it 我对过程边缘方法中发现的第三个条件[y]没有问题,因为如果它未被发现,那就意味着这是我们第一次看到它

I was confused with the check for parent[v] !== y but I guess it makes sense in the unweighted graph case, if we have a graph with just two nodes, both nodes have each other in their adjacency so this is not a cycle. 我对父[V]!== y的检查感到困惑,但我想在未加权的图形情况下它是有意义的,如果我们有一个只有两个节点的图形,两个节点彼此相邻,所以这不是一个周期。 I'm not clear though on why it would make sense in the directed case because 1->2 and 2->1 is considered a cycle, right? 我不清楚为什么它会在定向案例中有意义,因为1-> 2和2-> 1被认为是一个循环,对吧?

I disagree with the other answers on this. 我不同意其他答案。 A cycle does not visit an edge multiple times, otherwise any graph with an edge, directed or not, would have a cycle. 循环不会多次访问边缘,否则任何带有边缘的图形,无论是否有定向,都会有一个循环。 The algorithm given in the book is correct. 书中给出的算法是正确的。 The check is only needed for undirected graphs, but the code handles both very cleanly in my opinion. 只有无向图才需要检查,但在我看来,代码处理得非常干净。

If you're referring to a case when we might have two directed edges: 如果你指的是我们可能有两个有向边的情况​​:

1 -> 2
2 -> 1

Then whether or not you consider this a cycle is debatable. 那么你是否认为这个循环是值得商榷的。 In general, directed graphs are assumed not to have such cases. 通常,假定有向图不具有这种情况。 I can interpret such a pair as an undirected edge, and then it won't make sense to walk it twice. 我可以将这样的一对解释为无向边缘,然后将它走两次是没有意义的。 You can interpret it as two directed edges, and then you'd be right that the algorithm is wrong. 您可以将其解释为两个有向边,然后您认为该算法是错误的。 But it would only be wrong for your interpretation. 但是你的解释只会是错误的。

For the interpretation most often used (and easiest to understand), the algorithm does what it's supposed to. 对于最常使用的解释(并且最容易理解),算法会按照预期的方式执行。

As another example, one can also allow edges like 1 -> 1 . 作为另一个例子,人们也可以允许像1 -> 1这样的边。 Would you consider this a cycle? 你会认为这是一个循环吗? You wouldn't be wrong either way. 无论哪种方式,你都不会错。 It's just a matter of definitions. 这只是一个定义问题。 For textbooks, one usually works with the definition that lets the author present the most convenient (easiest to understand) solution. 对于教科书,人们通常使用的定义可以让作者呈现最方便(最容易理解)的解决方案。

  1. It is possible for directed graphs. 有向图是可能的。 Let's assume that we a have graph with 2 vertices and 1 edge: 2 -> 1. If we start the depth-first search from the first vertex, it will be processed by the time we visit the second vertex. 让我们假设我们有一个包含2个顶点和1个边的图:2 - > 1.如果我们从第一个顶点开始深度优先搜索,它将在我们访问第二个顶点时进行处理。 So an edge 2 -> 1 will lead to a processed vertex. 因此边缘2 - > 1将导致处理的顶点。 It is not possible for undirected graphs, though. 但是,无向图是不可能的。

  2. I agree with you here. 我同意你的看法。

The main issue with this code, in my opinion, is that it tries to handle both: directed and undirected graphs at the same time, which makes the logic unclear and hard to follow. 在我看来,这个代码的主要问题是它试图同时处理两个:有向图和无向图,这使得逻辑不清楚并且难以遵循。 Detecting cycles in a graph using depth-first search is actually pretty easy, so I would just recommend finding a better implementation(or making your own, which handles directed and undirected graphs separately). 使用深度优先搜索检测图形中的循环实际上非常简单,因此我建议您找一个更好的实现(或自己创建,分别处理有向和无向图)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM