Search code examples
c++graphcycledepth-first-search

Detecting and printing cycle in undirected graph


I have question similar - same - as this one. So I want to know how to not only detect cycle but also print out vertices which this cycle contains. I tried ways which were mentioned in the question above, but I must have done something wrong, why it doesn't work for my. Also my program checks just if one specific vertex makes cycle. My code is here:

#include<iostream>
#include <list>
using namespace std;


class Graph
{
    int V;    
    list<int> *adj;    
public:
    Graph(int V);   
    void addEdge(int v, int w);   
    bool Graph::isCyclicUtil(int v, bool visited[], int *cycleVertices, int parent, int index);
};

Graph::Graph(int V)
{
    this->V = V;
    adj = new list<int>[V];
}

void Graph::addEdge(int v, int w)
{
    adj[v].push_back(w); 
    adj[w].push_back(v);
}


bool Graph::isCyclicUtil(int v, bool visited[], int *cycleVertices, int parent, int index)
{

    visited[v] = true;


    list<int>::iterator i;
    for (i = adj[v].begin(); i != adj[v].end(); ++i)
    {

        if (!visited[*i])
        {
            if (isCyclicUtil(*i, visited, cycleVertices, v, index)) {
                if (index <= 1 || cycleVertices[0] != cycleVertices[index - 1])
                    cycleVertices[index++] = *i;
                return true;
            }
        }

        else if (*i != parent) {
            cycleVertices[index++] = *i;
            return true;
        }
    }
    return false;
}


int main()
{
    bool *visited = new bool[5];
    for (int i = 0; i < 5; i++)
        visited[i] = false;
    int cycleVertices[5];
    for (int i = 0; i < 5; i++)
        cycleVertices[i] = -1;
    Graph g1(5);
    g1.addEdge(1, 0);
    g1.addEdge(0, 2);
    g1.addEdge(2, 1);
    g1.addEdge(0, 3);
    g1.addEdge(3, 4);
    g1.isCyclicUtil(4, visited, cycleVertices, -1, 0) ? cout << "Graph contains cycle\n" :
        cout << "Graph doesn't contain cycle\n";
    int x = 0;
    while (cycleVertices[x] != -1)
        cout << cycleVertices[x++] << " ";
    return 0;
}

Solution

  • I've found a solution. I've tried j_random_hacker's solution in this post and it didn't work. But problem was with indexing in cycleVertices in my code. Variable index was always same. So I've added a new attribute index in the class Graph and now it works. So here is the edited code:

    #include<iostream>
    #include <list>
    
    #define FINISHED -1
    #define NOCYCLE -2
    using namespace std;
    
    
    class Graph
    {
        int V;   
        int index;
        list<int> *adj;   
    public:
        Graph(int V);   
        void addEdge(int v, int w);  
        void set_index();
        int Graph::isCyclicUtil(int v, bool visited[], int *cycleVertices, int parent);
    };
    
    Graph::Graph(int V)
    {
        this->V = V;
        adj = new list<int>[V];
        this->index = 0;
    }
    
    void Graph::set_index()
    {
        this->index = 0;
    }
    
    void Graph::addEdge(int v, int w)
    {
        adj[v].push_back(w); 
        adj[w].push_back(v); 
    }
    
    int Graph::isCyclicUtil(int v, bool visited[], int *cycleVertices, int parent)
    {
        visited[v] = true;
    
        list<int>::iterator i;
        for (i = adj[v].begin(); i != adj[v].end(); ++i)
        {
            if (!visited[*i])
            {
                int result = isCyclicUtil(*i, visited, cycleVertices, v);
                if (result == FINISHED)
                    return FINISHED;
                else if (result != NOCYCLE) {
                    cycleVertices[index++] = v;
                    if (result == v)
                        return FINISHED;
                    else
                        return result;
                }
            }
    
            else if (*i != parent) {
                return *i;
            }
        }
        return NOCYCLE;
    }
    
    
    int main()
    {
        bool *visited = new bool[4];
        for (int i = 0; i < 4; i++)
            visited[i] = false;
        int cycleVertices[4];
        for (int i = 0; i < 4; i++)
            cycleVertices[i] = -1;
        Graph g1(4);
        g1.addEdge(0, 1);
        g1.addEdge(1, 2);
        g1.addEdge(2, 3);
        g1.addEdge(3, 0);
        g1.isCyclicUtil(3, visited, cycleVertices, -1) ? cout << "Graph contains cycle\n" :
            cout << "Graph doesn't contain cycle\n";
        int x = 0;
        while (cycleVertices[x] != -1)
            cout << cycleVertices[x++] << " ";
        return 0;
    }