Hi guys so I am making function for my graphs (adjacency matrices) to return number of connected components using breadth first search algorithm.
It almost works properly. It returns proper value if number of components is equal to number of vertices, but if number of components is smaller than number of vertices it returns (proper value +1). I have no idea how to fix it, so if you could give it a look and tell me I would be glad. Heres the link to the code it looks more decent then the one below http://wklej.org/id/861341/
int Graph::getNumberOfConnectedComponents()
{
int components=0;
queue<int> S;
int n = getVerticesCount();//as name indicates it returns number of vertices in graph
bool* visited = new bool[n];
for(int i=1;i<n;i++)
visited[i]=false;
visited[0]=true;
S.push(0);
while(!S.empty())
{
int v = S.front();
S.pop();
list<int> x = getNeighbors(v);//as name indicates this function returns list of neighbours of given vertice
if(!x.empty())
{
list<int>::iterator it;
for (it=x.begin(); it!=x.end(); it++)
{
if(visited[*it]==false)
{
S.push(*it);
visited[*it]=true;
}
}
}
if(S.empty())
{
components++;
for(int i=1;i<n;i++)
{
if(visited[i]==false)
{
S.push(i);
visited[i]=true;
break;
}
}
}
}
return components;
}
I explained what those functions do in comments, hope you will be able to help me :/ . Btw if you change place of components++; and put it into if(visited[i]==false) it gives proper value for all graphs except those which number of components = number of vertices (for those this value is "proper value-1").
#Edit 1 , here is this function john
list<int> AdjacencyMatrixGraph::getNeighbors(int v)
{
list<int> x;
if(v==0||v>=n)
return x;
for(int j=0;j<n;j++)
{
if(matrix[v][j]!=0)
x.push_front(j);
}
return x;
}
list<int> AdjacencyMatrixGraph::getNeighbors(int v)
{
list<int> x;
if(v==0||v>=n)
return x;
should be
list<int> AdjacencyMatrixGraph::getNeighbors(int v)
{
list<int> x;
if(v<0||v>=n)
return x;
vertex 0 can have neighbors as far as I can tell.
Related
Hi I am try to implement a graph using adjacency list using following code.
#include<iostream>
#include<list>
#include<vector>
#include<unordered_map>
using namespace std;
class graph{
public:
vector<int> adj[10000];
void insert(int u,int v, bool direction) {
adj[u].push_back(v);
if(direction==1) {
adj[v].push_back(u);
}
}
void print(int n) {
for(int i=0;i<n+1;i++) {
cout<<i<<"->";
for(auto j : adj[i]) {
cout<<j<<",";
}
cout<<endl;
}
}
};
int main( ) {
int n;
cout<<"Enter no of node"<<endl;
cin>>n;
cout<<"enter edges "<<endl;
int m;
cin>>m;
graph g;
for(int i=0;i<m;i++) {
int u, v;
cin>>u>>v;
g.insert(u,v,1);
}
g.print(n);
return 0;
}
But the problem with this code is that it will give correct answer only in the case when my node start from 0 in a continuous manner(0,1,2,3). But when I try to print adjacency list of this graph:
Then it is giving this output:
Can somebody tell me where am I wrong?
The edges you are adding aren't the same as the graph i picture, you are inputting edge 1, 3 instead of edge 1, 5.
It's printing the 0 because you started that for loop from i = 0 and it doesn't print node 5 for the same reason (the loop ends at 4 because you will have i < 4 + 1.
void print(int n) {
//↓↓↓ HERE
for(int i=0;i<n+1;i++) {
cout<<i<<"->";
for(auto j : adj[i]) {
cout<<j<<",";
}
cout<<endl;
}
}
Here is how I would change your code:
First, I changed the print() function a little (added the if() to see if the current row is empty and I changed the int n parameter to int maximum which will hold the highest value node so we know when to stop the for).
void print(int maximum)
{
for(int i=0; i<=maximum; i++)
{
if(!adj[i].empty())
{
cout<<i<<"->";
for(auto j : adj[i])
{
cout<<j<<",";
}
cout<<endl;
}
}
}
Then, in main() I added the maximum and aux variables in order to store the aforementioned highest value node. And I also changed the g.print(n) to g.print(maximum).
int main( )
{
int n, maximum = 0, aux;
cout<<"Enter no of node"<<endl;
cin>>n;
cout<<"enter edges "<<endl;
int m;
cin>>m;
graph g;
for(int i=0; i<m; i++)
{
int u, v;
cin>>u>>v;
g.insert(u,v,1);
aux = max(u, v);
maximum = max(maximum, aux);
}
g.print(maximum);
return 0;
}
However, I might not be Terry A. Davis, but I know that if you say you have 4 nodes, those 4 nodes will be 1 2 3 and 4. And I also know that any graph related problem will have nodes starting from 1, therefore every for loop would start from i = 1, or at least that's how I was taught. The way you did it might be correct too, but I am not sure.
I have written a code for this but it gives segmentation fault for disconnected graphs. It works fine for graphs that are connected.
How can I overcome this error?
vector<int> getPathBFS(int V, int** edges,int v1, int v2, int* visited, unordered_map<int,int> t)
{
queue<int> q;
q.push(v1);
visited[v1]=1;
int done=0;
while(!q.empty() && done==0)
{
for(int i=0;i<V;i++)
{
int front=q.front();
q.pop();
if(edges[front][i]==1 && visited[i]!=1)
{
q.push(i);
t[i]=front;
visited[i]=1;
if(i==v2)
{
done=1;
break;
}
}
}
}
vector<int> a;
if(done==0)
return a;
else
{
int k=v2;
a.push_back(v2);
while(k!=v1)
{
k=t[k];
a.push_back(k);
}
return a;
}
}
int main()
{
int V, E;
cin >> V >> E;
int** edges=new int*[V];
for(int i=0;i<V;i++)
{
edges[i]=new int[V];
for(int j=0;j<V;j++)
{
edges[i][j]=0;
}
}
for(int i=0;i<E;i++)
{
int f,s;
cin>>f>>s;
edges[f][s]=1;
edges[s][f]=1;
}
int v1,v2;
cin>>v1>>v2;
int* visited=new int[V];
for(int i=0;i<V;i++)
visited[i]=0;
unordered_map<int,int> t;
t[v2]=0;
vector<int> ans=getPathBFS(V,edges,v1,v2,visited,t);
for(int i=0;i<ans.size();i++ && !ans.empty())
{
cout<<ans[i]<<" ";
}
delete [] visited;
for(int i=0;i<V;i++)
{
delete [] edges[i];
}
delete [] edges;
return 0;
}
I did a dry run of the code. It will first create adjacency matrix edges and mark all the edges in it. Visited array is used to keep track of all the vertices that have been visited till now so that there is no infinite loop.
For the test case given below it will work till the queue contains 1 then it will pop 1 and the loop will end because there is no edge left that is connected to 1 and is not visited. After this the while loop should ideally break and as done==0 it should return an empty vector. I can't understand why the segmentation fault is coming.
The map is being used to keep track of which vertex was put in the queue by which vertex.
Doesn't work for the test case:
6 3
5 3
0 1
3 4
0 3
Below is the image of the graph for the above test case:
Here we need to find the path from vertex 0 to 3.
The input format is :
Number of Vertices in the graph, Number of edges
Edges between the vertices (for E lines),
Vertices between which we need to find the path.
You are popping the BFS queue incorrectly. Instead of the inner for loop, which is executed |V| times for each entry in the queue, you should pop the queue in the outer loop, which is executed once for each element in the queue.
vector<int> getPathBFS(int V, int** edges,int v1, int v2, int* visited, unordered_map<int,int> t)
{
queue<int> q;
q.push(v1);
visited[v1]=1;
int done=0;
while(!q.empty() && done==0)
{
int front=q.front();
q.pop();
for(int i=0;i<V;i++)
{
if(edges[front][i]==1 && visited[i]!=1)
{
q.push(i);
t[i]=front;
visited[i]=1;
if(i==v2)
{
done=1;
break;
}
}
}
}
vector<int> a;
if(done==0)
return a;
else
{
int k=v2;
a.push_back(v2);
while(k!=v1)
{
k=t[k];
a.push_back(k);
}
return a;
}
}
Also, in main function of your code, there is a redundant expression !ans.empty() in the for loop where you are printing the answer(s).
I have been trying to do a graph search for a problem from Hackerrank. Lastly, I have come up with
#include <cstdio>
#include <list>
using namespace std;
void bfs(list<int> adjacencyList[], int start, int countVertices) {
// initialize distance[]
int distance[countVertices];
for(int i=0;i < countVertices; i++) {
distance[i] = -1;
}
list<int>::iterator itr;
int lev = 0;
distance[start-1] = lev; // distance for the start vertex is 0
// using start -1 since distance is array which are 0-indexed
list<int> VertexQueue;
VertexQueue.push_back(start);
while(!VertexQueue.empty()) {
int neighbour = VertexQueue.front();
itr = adjacencyList[neighbour].begin();
while(itr != adjacencyList[neighbour].end()) {
int vertexInd = (*itr) - 1;
if(distance[vertexInd] == -1) { // a distance of -1 implies that the vertex is unexplored
distance[vertexInd] = (lev + 1) * 6;
VertexQueue.push_back(*itr);
}
itr++;
}
VertexQueue.pop_front();
lev++;
}
// print the result
for(int k=0;k< countVertices;k++) {
if (k==start-1) continue; // skip the start node
printf("%d ",distance[k]);
}
}
int main() {
int countVertices,countEdges,start,T,v1,v2;
scanf("%d", &T);
for(int i=0; i<T; i++) {
scanf("%d%d", &countVertices,&countEdges);
list<int> adjacencyList[countVertices];
// input edges in graph
for(int j=0; j<countEdges; j++) {
scanf("%d%d",&v1,&v2);
adjacencyList[v1].push_back(v2);
adjacencyList[v2].push_back(v1); // since the graph is undirected
}
scanf("%d",&start);
bfs(adjacencyList, start, countVertices);
printf("\n");
}
return 0;
}
However, this is resulting in 'Segmentation Fault' and I cannot figure out where I am going wrong.
Also, I have comes across segmentation fault a lot of times, but have no idea how to debug it. Would be great if someone can give me an idea of that.
scanf("%d%d", &countVertices,&countEdges);
list<int> adjacencyList[countVertices];
Above code appears wrong. If your indices start with 1, either make adjacencyList of size countVertices + 1 or decrease u and v before putting them in the list.
You can also use a (an unordered) map mapping vertex to a list which will not segfault.
Also not that VLA are not part of standard C++, so avoid them even if your compiler support them as extension.
Given a unweighted and undirected tree with N nodes and N-1 edges I need to find minimum distance between source S and destination D.
Code :
vector<vector<int> >G(110);
bool check(int node,vector<int>path)
{
for(int i=0;i<path.size();++i)
{
if(path[i]==node)
return false;
}
return true;
}
int findMinpath(int source,int target,int totalnode,int totaledge)
{
vector<int>path;
path.push_back(source);
queue<vector<int> >q;
q.push(path);
while(!q.empty())
{
path=q.front();
q.pop();
int lastNode=path[path.size()-1];
if(lastNode==target)
{
return path.size()-1;
}
for(int i=0;i<G[lastNode].size();++i){
if(check(G[lastNode][i],path)){
vector<int>new_path(path.begin(),path.end());
new_path.push_back(G[lastNode][i]);
q.push(new_path);
}}}
return 1;
}
And then in main :
int N,S,E;
cin>>N>>S>>E;
for(int i=1;i<=N-1;++i)
{
int u,v;
cin>>u>>v;
G[u].push_back(v);
G[v].push_back(u);
}
cout<<findpaths(S,E,N,N-1)<<"\n";
Can it be further optimised as I need just minimum distance between S and E
You seem to be pushing vectors to your queue, each vector containing the actual path so far. But you can get away with only pushing nodes, since you only use the last node in those vectors anyway, and instead store the distance to each node from the source.
This will be much faster because you won't be copying vectors at each step.
Keep track of the distances in an array and also use them to make sure you don't visit a node multiple times.
Untested, but should get the point across:
int distance[110 + 1]; // d[i] = distance from source to i, initialize with a large number
int findMinpath(int source,int target,int totalnode,int totaledge)
{
for (int i = 0; i <= totalnode; ++i)
{
distance[i] = 2000000000;
}
queue<int> q;
q.push(source);
distance[source] = 0;
while(!q.empty())
{
node=q.front();
q.pop();
if(node==target)
{
return distance[node];
}
for(int i=0;i<G[node].size();++i){
if(distance[node] + 1 < distance[ G[node][i] ]){
distance[ G[node][i] ] = distance[node] + 1
q.push(G[node][i]);
}}}
return 1;
}
In the input specification N the number of nodes and M the number of edges are given . So the first simple check is that M should be equal to N-1 otherwise it simply can't be a tree.
What I did next was just a DFS in which I see that whether during the DFS we come across a visited a node again ( different from the parent node, by parent node I mean the node which has called the dfs of the next node adjacent to it ) then it means that we have a cycle and it isn't a tree . But apparently my solution keeps on getting a wrong answer . I am posting the code but only the snippets that are important . I am storing the graph as a adjacency list and I am posting the function isTree() which tests whether it is a tree or not ? What is the correct logic ?
#include <iostream>
#include <list>
using namespace std;
// Graph class represents a directed graph using adjacency list representation
class Graph
{
int V; // No. of vertices
list<int> *adj; // Pointer to an array containing adjacency lists
bool isTreeUtil(int v, bool visited[],int parent);
public:
Graph(int V); // Constructor
void addEdge(int v, int w); // function to add an edge to graph
bool isTree(); // Tells whether the given graph is a tree or not
void printGraph();
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V+1];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
adj[w].push_back(v);
}
bool Graph::isTreeUtil(int v, bool visited[],int parent)
{
//int s_v = v;
visited[v] = true;
list<int>::iterator i;
for(i = adj[v].begin(); i != adj[v].end(); ++i) {
if (!visited[*i])
isTreeUtil(*i,visited,v);
else {
if (*i != parent && visited[*i])
return false;
}
}
return true;
}
bool Graph::isTree() {
bool *visited = new bool[V+1];
for(int i = 1; i < V+1; i++)
visited[i] = false;
visited[1] = true; // marking the first node as visited
for(int i = 1; i < V+1; i++)
visited[i] = false;
int parent = -1; // initially it has no parent
//list<int> :: iterator i;
//for (i = adj[v].begin(); i != adj[v].end(); ++i)
return isTreeUtil(1, visited, parent);
}
void Graph::printGraph() {
for (int i = 1;i <= this->V; i++) {
cout << i << "->";
list<int>::iterator j;
for (j = adj[i].begin(); j != adj[i].end(); ++j) {
cout << *j << "->";
}
cout << "\n";
}
}
int main() {
int N, M;
cin >> N >> M;
Graph G(N);
int v, w;
int m = 0;
while (m < M) {
cin >> v >> w;
G.addEdge(v,w);
m++;
}
if (M != N-1) {
cout << "NO\n";
else if (G.isTree())
cout << "YES\n";
else
cout << "NO\n";
}
I took your code, compiled, and ran it on my machine. When implementing a graph, there are important specs to consider. When you choose to obey a spec, it is generally good practice to enforce that spec in your code.
It is already clear that the graph has 2-way edges, though it does not hurt to specifically mention this.
Allow Duplicate Edges?
Your program allows me to make edge (1,2) and then another edge (1,2) and count it as 2 edges. This makes your conditional M != N-1 an insufficient check. Either disallow duplicate edges or account for them in your algorithm (currently, a duplicate edge will cause your algorithm to return incorrectly).
Self Edges?
Does your graph allow a vertex to have an edge to itself? If so, should the self-path invalidate the tree (perhaps a self-loop is legal because in a tree, every node can access itself)? Currently, self edges also break your algorithm.
To help you, here is my revised implementation of addEdge() that disallows duplicate edges and disallows self-loops. As a bonus it also checks for array bounds ;)
Please note that the additional include, and the change in function signature (it now returns a bool).
#include <algorithm>
bool Graph::addEdge(int v, int w)
{
// sanity check to keep us from seg faulting
if (v < 1 || v > this->V || w < 1 || w > this->V) {
return false;
}
// no self-edges
if (w == v) {
return false;
}
// no duplicate edges allowed either
std::list<int>::iterator findV = std::find(adj[v].begin(), adj[v].end(), w);
std::list<int>::iterator findW = std::find(adj[w].begin(), adj[w].end(), v);
if (findV != adj[v].end() || findW != adj[w].end()) {
return false;
}
adj[v].push_back(w); // Add w to v’s list.
adj[w].push_back(v);
return true;
}
I hope this helps. If this is an assignment, you should review the write-up. They must have specified these cases if your implementation was auto-graded. As #congusbongus mentioned, your algorithm also fails in the case of a disconnected node.
Please note that you also have to revise the main() method in order for my implementation to work. Change this part of the function:
while (m < M) {
cout << "Create Edge from x to y" << endl;
cin >> v >> w;
if (!G.addEdge(v,w)) {
cout << ">>Invalid edge not added" << endl;
} else {
cout << ">>Successfully added edge" << endl;
m++;
}
}
it runs for all the simple test cases I drew on paper but when submitting it fails !
Sounds like some auto-marking system for homework right? If you had access to the exact test cases, then the problem would be obvious. In this case it's probably not available, so we can only speculate.
In my experience, most failures of this kind are due to missed boundary cases. You say you check for number of edges = number of nodes - 1, but have you also considered the following?
All nodes connected
No more than one edge per pair of nodes
That is, is your program prepared to return "NO" for this?
_
/ \
o o---o
Nodes: 3, edges: 2