-3

I want to know whether my graph is bipartite or not, I have several test cases. If I run more than one test case it doesn't work properly, it always shows Bipartite. I am having a hard time figuring it out. For just one case, it works fine for any graph.
Here goes my code.

#include <iostream>
#include <cstdio>
#include <stack>
#include <list>

using namespace std;

class Graph
{
    public:
        int V;
        list<int> *adj;
        Graph(int V);
        void addEdge(int v, int w);
};

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);
}

class Bipartite
{
    private:
        bool isBipartite;
        bool *color;
        bool *marked;
        int *edgeTo;
        stack<int> cycle;
    public:
        Bipartite(Graph G)
        {
            isBipartite = true;
            color = new bool [G.V];
            marked = new bool [G.V];
            edgeTo = new int [G.V];
            for (int v = 0; v < G.V; v++)
            {
                if (!marked[v])
                {
                    color[v] = false;
                    dfs(G, v);
                }
            }

            delete color;
            delete marked;
            delete edgeTo;
        }

        void dfs(Graph G, int v)
        {
            marked[v] = true;
            list<int>::iterator w;
            for (w = G.adj[v].begin(); w != G.adj[v].end(); w++)
            {
                if (!cycle.empty())
                    return;
                if (!marked[*w])
                {
                    edgeTo[*w] = v;
                    color[*w] = !color[v];
                    dfs(G, *w);
                }
                else if (color[*w] == color[v])
                {
                    isBipartite = false;
                    cycle.push(*w);
                    for (int x = v; x != *w; x = edgeTo[x])
                    {
                        cycle.push(x);
                    }
                    cycle.push(*w);
                }
            }
        }

        bool isBi()
        {
            return isBipartite;
        }
};

void solve(int n,int **p){
    long long int x,y;
    Graph g(n);

    for(x=0;x<n;x++)
        for(y=0;y<n;y++)
        {
            if(p[x][y]==1)
                g.addEdge(x,y);
        }

    Bipartite b(g);
    if (b.isBi())
        cout<<"YES"<<endl;
    else
        cout<<"NO"<<endl;
}

int main()
{

    long long int i,j,t,x,m,y,a,b;
    int **p,n;

    cin>>t;

    for(i=0;i<t;i++)
    {
        cin>>n>>m;

        p=new int*[n]();
        for(x=0;x<n;x++)
        {
            p[x]=new int[n]();
        }

        for(j=0;j<m;j++)
        {
            cin>>a>>b;
            a=a-1;
            b=b-1;

            p[a][b]=1;
            p[b][a]=1;

        }

        for(x=0;x<n;x++)
        {
            for(y=0;y<n;y++)
            {
                if(x!=y)
                {
                    p[x][y]=1-p[x][y];
                }
            }
        }

        /*  for(x=0;x<n;x++)
        {
            for(y=0;y<n;y++)
                cout<<p[x][y]<<" ";
            cout<<"\n";
        }
        */

        solve(n,p);
    }
    return 0;
}
Born2Code
  • 99
  • 6

2 Answers2

2

You never explicitly initialize the contents of marked, or, more accurately, the contents of the array that it points to.

The loop in your constructor reads elements of marked to decide how to assign to color, but you never initialized the elements of marked being read.

Similiar argument for color and edgeTo.

This means that, while they may have had the expected initializations for the first case, may well be using whatever value happened to be there in later cases.

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
  • 1
    Explicitly initialize your variables. – Scott Hunter Sep 09 '16 at 16:35
  • Assign them values. – Scott Hunter Sep 09 '16 at 16:40
  • Now the code works fine but my actual problem is: it doesn't pass all test cases. My actual problem is: I want to actually check whether I can partition my graph into two Cliques(complete subgraph). What I did is complement the adjacency matric and check for Bipartite. But it doesn't work, any idea why? – Born2Code Sep 09 '16 at 16:54
  • If it doesn't pass all test cases, then it doesn't "work fine". – Scott Hunter Sep 09 '16 at 17:02
  • The problem which I have mentioned above got solved, but actual question is to check: "whether I can partition my graph into two Cliques(complete subgraph). My approach: What I did is complement the adjacency matrix and check for Bipartite" – Born2Code Sep 09 '16 at 17:05
  • That was not your original question, the one you posted, and got 2 answers for. Maybe you should this as a new question. – Scott Hunter Sep 09 '16 at 17:07
  • Actual question is: there are actually two cities, all the people in a city must know each other, otherwise they feel very unsafe. [The values which I enter are the people (in adjacency matrix)]. So, I must check whether it is possible! – Born2Code Sep 09 '16 at 17:09
0

Also Bipartite(Graph G) is calling the default copy constructor of Graph. Probably not what you want.

Try Bipartite(const Graph & G) instead (also in dfs).

And don't do new without delete.

Rather use vector<vector<int>> adj;, why even list? And reinit it in constructor with adj.resize(V);.


After your edit of code in question, as you use new to allocate array, you should delete it as array too, so use delete[] color;.

Or stop using new/delete completely. Again you can use std::vector<bool> color(G.V);, avoiding both new/delete hassle, and also having all values initialized to false by default.

In modern C++ there're very few (more like "none") reasons to ever use new or delete (unless you write some low level library, or you are optimizing for performance, and you know what you are doing).

Ped7g
  • 16,236
  • 3
  • 26
  • 63
  • Now the code works fine but my actual problem is: it doesn't pass all test cases. My actual problem is: I want to actually check whether I can partition my graph into two Cliques(complete subgraph). What I did is complement the adjacency matric and check for Bipartite. But it doesn't work, any idea why? – Born2Code Sep 09 '16 at 17:01
  • @Born2Code I'm not sure whether I get the task description. So if you have two people, connected, then answer is "yes"? (each form his own city = clique, the connection between them is ignored) Then your complement of adjacency will be empty edge set? I didn't check your source, will it answer as "bipartition = OK"?. Anyway, I'm a bit too rusty in graph theory to decide whether your idea is correct, but can't see obvious problem with it (except that bi-partitioning has to handle separated sub graphs). But I'm too lazy to check your code. – Ped7g Sep 09 '16 at 17:26
  • Check this: [link](https://s17.postimg.io/pu5ffxp7z/Untitled.jpg) In 1st case, I can divide them and put them into two cities, 1 in one city and 2 &3 in another city. [since 2 and 3 know each other] In second case, I can't separate them as they can't be split in said condition. [as if I split, they all won't be knowing each other] In third case, I can separate into two groups, 1,2,3 in one group and 4,5,6 in another group. Since they all know each other. – Born2Code Sep 09 '16 at 17:33
  • @Born2Code looks ok on first sight. Keep looking for failing test case and debug (verify also single citizen input, no citizen input, full graph input, etc). But the code you posted looks to be prone to have memory leaks, unitialized values, etc, so it may fail also due to bug in code, not only in logic. Get also some good books on modern C++/tutorials, and keep checking them. Maybe do some easier task first, and when you are sure it's working, post it for codereview. Or on many task sites after solving task you may check others solutions, although rarely they will promote quality source. – Ped7g Sep 09 '16 at 17:46
  • You may want for example to learn how to use valgrind, that would help with those uninitialized values. – Ped7g Sep 09 '16 at 17:47