5

So, I implemented the DFS in an iterative manner by the following method:

void dfsiter (graph * mygraph, int foo, bool arr[])
{
    stack <int> mystack;
    mystack.push(foo);
    while (mystack.empty() == false)
    {
        int k = mystack.top();
        mystack.pop();
        if (arr[k] == false)
        {
            cout<<k<<"\t";
            arr[k] = true;
            auto it = mygraph->edges[k].begin();
            while (it != mygraph->edges[k].end())
            {
                if (arr[*it] == false)
                {
                    mystack.push(*it);
                }
                it++;
            }

        }
    }
}

The above code works completely fine. Now, I want to detect cycles in an undirected graph using the above code (Iterative DFS). Now, I read that, If an unexplored edge leads to a node visited before, then the graph contains a cycle. Therefore, I just want to ask you, how do I exactly keep track of all this?

I have taken my graph to be like this:

class graph
{
    public:
    int vertices;
    vector < vector<int> > edges;
};

Should I change the above to:

class graph
{
    public:
    int vertices;
    vector < vector<pair<int,bool> > edges;
};

Where the bool for each edge will be marked true? And what changes will I need to do in the above code for DFS for detecting the cycle? I tried but I couldn't really think of a way of doing it. Thanks!

John Lui
  • 1,434
  • 3
  • 23
  • 37
  • What exactly do you want to receive as output data? – stgatilov Jul 21 '15 at 07:41
  • I am trying to modify the above iterative DFS for detecting whether there exists a cycle in the undirected graph or not. After doing so, I will try and do it for a directed graph. But I am not really sure, how to modify the above graph to store the required information for finding out such information. – John Lui Jul 21 '15 at 07:43
  • Isn't the array arr a way to check if a node is already visited? Why you need to modify the graph class to add this information? – Gerard Abello Jul 21 '15 at 07:46
  • But only by using arr, how will I check for a cycle? – John Lui Jul 21 '15 at 07:49
  • Maybe I'm wrong, but in this loop: if (arr[*it] == false){ mystack.push(*it); } If you detect that arr[*it] is true, I think you just detected a cycle. In this case, the edge is unexplored because you just visited k for the first time and you found a visited node. – Gerard Abello Jul 21 '15 at 07:57

1 Answers1

11

You can store a "father" node f in DFS tree for each vertex v, i.e. the vertex from which DFS came to the vertex v. It can be stored in the stack for example. In this case you store pairs in stack, first value is the vertex v and the second one is its father f.

An undirected graph has a cycle if and only if you meet an edge vw going to already visited vertex w, which is not the father of v.

You can see the modified and cleaned code below.

bool hascycle (graph * mygraph, int start, bool visited[])
{
    stack <pair<int, int> > mystack;
    mystack.push(make_pair(start, -1));
    visited[start] = true;

    while (!mystack.empty())
    {
        int v = mystack.top().first;
        int f = mystack.top().second;
        mystack.pop();

        const auto &edges = mygraph->edges[v];
        for (auto it = edges.begin(); it != edges.end(); it++)
        {
            int w = *it;
            if (!visited[w])
            {
                mystack.push(make_pair(w, v));
                visited[w] = true;
            }
            else if (w != f)
                return true;
        }
    }
    return false;
}

Note: if the graph is disconnected, then you must start DFS from several vertices, ensuring that the whole graph is visited. It can be done in O(V + E) total time.

stgatilov
  • 5,333
  • 31
  • 54
  • 2
    Hi, this is perfect. Can you also tell me how can I modify it for a directed graph? Thanks! :) – John Lui Jul 21 '15 at 09:53
  • 1
    You mean, I do, `if (!visited[w]) { ... } else return true?` Something like this? – John Lui Jul 21 '15 at 10:53
  • 1
    But I don't think so, this will work. Consider the graph with the following edges, `1->2, 1->3, 2->4, 3->4`. Here, their is no cycle, yet it will output there is a cycle since it explores 4 while traversing 3 and then when it comes to 2, 4 is already marked as true. – John Lui Jul 21 '15 at 10:59