Memory leak in Depth First Search Algorithm on Graphs - c++

I was doing a course on Coursera where they asked to implement DFS to see if two vertices of a graph are connected. I came up with the code and it gives the correct output on my laptop but it gives incorrect output on their grader. I've been breaking my head for days on this problem and have absolutely no idea where I've gone wrong. The code is as follows:
#include<iostream>
#include<vector>
using namespace std;
class Graph
{
public:
vector<int> adj; //adjacency list
void add(int a)
{
adj.push_back(a);
}
void DFS(bool visited[],int n,Graph G[],int v)
{
for(int i=0;i<G[v].adj.size();i++)
{
int vert=G[v].adj[i];
if(visited[vert]==false)
{
visited[vert]=true;
DFS(visited,n,G,vert);
}
}
}
};
int main()
{
int n,m;
cin>>n>>m;//No. of vertices,number of edges
bool visited[n];
for(int i=0;i<n;i++)
visited[n]=false;
Graph G[n];
for(int i=0;i<m;i++)
{
int u,v;
cin>>u>>v; //The vertices joined by two edges
G[u-1].add(v-1);
G[v-1].add(u-1);
}
int k,l;
cin>>k>>l; //The vertices to be checked if they are connected
G[k-1].DFS(visited,n,G,k-1);
if(visited[l-1]==true)
cout<<1;
else
cout<<0;
}
Grader Output:
Failed case #2/16: (Wrong answer)
Input:
4 2
1 2
3 2
1 4
Your output:
1
Correct output:
0
(Time used: 0.00/1.00, memory used: 7839744/536870912.)
If I run the above case in my laptop, it gives the output as 0, the expected answer. I asked the question on the forum and they say that there is some memory leak which I can't identify. Please help.

If you're writing a Graph class, then you should really encapsulate all functionality inside that class. You're not supposed to overwhelm the main function. It makes your code convoluted. Plus you don't have to pass around a lot things in case of a function call. Avoid using using namespace std; as it will lead to namespace collision. To avoid writing std::cout or std::cin, consider using std::cout and using std::cin. I refactored your code and now it gives correct output:
#include <iostream>
#include <cstring>
#include <vector>
using std::cout;
using std::cin;
class Graph
{
public:
static constexpr int MAXN = 100;
std::vector <int> adj[MAXN + 1]; //adjacency list
int visited[Graph::MAXN + 1]; // for 1 based indexing
Graph(){
for(int i = 0 ; i <= MAXN ; ++i) adj[i].clear();
memset(visited, 0, sizeof(visited));
}
void addEdge(bool isDirected, int u, int v)
{
adj[u].push_back(v);
if(!isDirected) adj[v].push_back(u);
}
void takeInput(bool isDirected, int nodes, int edges){
for(int i = 0 ; i < edges ; i++){
int u,v; cin >> u >> v;
addEdge(isDirected, u, v);
}
}
void DFS(int source)
{
visited[source] = 1;
for(int i = 0 ; i < adj[source].size() ; ++i){
int adjNode = adj[source][i];
if(visited[adjNode] == 0){
DFS(adjNode);
}
}
}
bool isConnected(int source, int destination){
DFS(source - 1);
return visited[destination - 1];
}
};
int main()
{
int nodes, edges;
cin >> nodes >> edges;//No. of vertices,number of edges
Graph g;
g.takeInput(false, nodes, edges);
int source, destination;
cin >> source >> destination; //The vertices to be checked if they are connected
cout << g.isConnected(source, destination) << '\n';
return 0;
}

Related

Adjacency List in graph

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.

What's wrong in my approach in a problem of game of death in a circle?

#include<bits/stdc++.h>
#include<vector>
#include<algorithm>
using namespace std;
void safe(int n,int k,int a[])
{
vector<int>s(a+0,a+n);
vector<int>b(a+0,a+n);
while(s.size()>1)
{
int r;
r=s.size();
int count=1;
while(count<=r)
{
b[count%r]=0;
count=count+k;
}
b.erase(remove(b.begin(),b.end(),0),b.end());
s=b;
}
for(int x:s)
{
cout<<x<<"\n";
}
}
int main()
{
int t;
cin>>t;
for(int i=0;i<t;i++)
{
int n,k;
cin>>n>>k;
int *a=new int[n];
for(int j=1;j<=n;j++)
{
a[j-1]=j;
}
if(n>2)
{
safe(n,k,a);
}
else if(n==2)
{
cout<<a[1]<<"\n";
}
else
cout<<a[0]<<"\n";
}
}
Input:
4
4 2
5 2
2 1
50 10
Output:
1
3
2
19 --> it should be 36
If you don't know this problem
Description of question:
There are n people standing in a circle (numbered clockwise 1 to n) waiting to be executed. The counting begins at point 1 in the circle and proceeds around the circle in a fixed direction (clockwise). In each step, a certain number of people are skipped and the next person is executed. The elimination proceeds around the circle (which is becoming smaller and smaller as the executed people are removed), until only the last person remains, who is given freedom.
Given the total number of persons n and a number k which indicates that k-1 persons are skipped and kth person is killed in circle. The task is to choose the place in the initial circle so that you are the last one remaining and so survive.
Consider if n = 5 and k = 2, then the safe position is 3.
Firstly, the person at position 2 is killed, then person at position 4 is killed, then person at position 1 is killed. Finally, the person at position 5 is killed. So the person at position 3 survives.
Here is a possible solution, hopefully the comments make it clear. There's no need to allocate an int[] and copy it into the vector, you can init the vector directly with iota. Likewise you can remove elements as you go, rather than zeroing and removing as a later step.
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
void safe(int n, int k) {
vector<int> s(n);
// Init the vector 1..n
iota(s.begin(), s.end(), 1);
int i = 0;
// While more than one survive...
while (s.size() > 1) {
// Skip forward (k-1)
i = (i + k - 1) % s.size();
// Kill the next one
s.erase(s.begin() + i);
}
for (int x : s) {
cout << x << "\n";
}
}
int main() {
int t;
cin >> t;
for (int i = 0; i < t; i++) {
int n, k;
cin >> n >> k;
if (n > 2) {
safe(n, k);
} else if (n == 2) {
cout << 2 << "\n";
} else
cout << 1 << "\n";
}
}

Why my C++14 KosaRaju algo getting TLE when a similar written code runs much faster

TLE code completes at 2.1 secs. I'm also passing many things through reference but it's still throwing a TLE. Why this code takes so much time?
here is the problem at hackerearth:
https://www.hackerearth.com/problem/algorithm/falling-dominos-49b1ed46/
Dominos are lots of fun. Children like to stand the tiles on their side in long lines. When one domino falls, it knocks down the next one, which knocks down the one after that, all the way down the line. However, sometimes a domino fails to knock the next one down. In that case, we have to knock it down by hand to get the dominos falling again. Your task is to determine, given the layout of some domino tiles, the minimum number of dominos that must be knocked down by hand in order for all of the dominos to fall.
Input
The first line of input contains one integer specifying the number of test cases to follow. Each test case begins with a line containing two integers, each no larger than 100 000. The first integer n is the number of domino tiles and the second integer m is the number of lines to follow in the test case. The domino tiles are numbered from 1 to n. Each of the following lines contains two integers x and y indicating that if domino number x falls, it will cause domino number y to fall as well.
Output
For each test case, output a line containing one integer, the minimum number of dominos that must be knocked over by hand in order for all the dominos to fall.
SAMPLE INPUT
1
3 2
1 2
2 3
SAMPLE OUTPUT
1
code completes at 2.1
#include <iostream>
#include <vector>
#include <unordered_set>
#include <stack>
using namespace std;
void dfs(const vector<vector<int>> &edges, unordered_set<int> &visited,int sv, stack<int> &stk){
visited.insert(sv);
for(int i=0;i<edges[sv].size();i++){
int current = edges[sv][i];
if(visited.find(current)==visited.end())
dfs(edges, visited, current, stk);
}
stk.push(sv);
}
void dfs(const vector<vector<int>> &edges, unordered_set<int> &visited,int sv){
visited.insert(sv);
for(int i=0;i<edges[sv].size();i++){
int current = edges[sv][i];
if(visited.find(current)==visited.end())
dfs(edges, visited, current);
}
}
int main()
{
int t;
cin>>t;
while(t--){
int V, E;
cin>>V>>E;
vector<vector<int>> edges(V+1);
unordered_set<int> visited;
stack<int> stk;
while(E--){
int f, s;
cin>>f>>s;
edges[f].push_back(s);
}
for(int i=1;i<=V;i++)
if(visited.find(i)==visited.end())
dfs(edges, visited, i, stk);
visited.clear();
int count{0};
while(!stk.empty()){
int current = stk.top();
stk.pop();
if(visited.find(current)==visited.end()){
dfs(edges, visited, current);
count++;
}
}
cout<<count<<endl;
}
return 0;
}
Efficient Code completes at 0.7 sec.
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
void dfs( vector<int> *edges , int start,int n,bool *visit ,stack<int> *nodex)
{
visit[start] = true;
// cout<<start<<endl;
for (int i = 0; i < edges[start].size(); ++i)
{
int next = edges[start][i];
if(visit[next] == false)
dfs(edges,next,n,visit,nodex);
}
nodex->push(start);
}
void dfs(vector<int> *edges,int start, bool *visit,int n)
{
visit[start] = true;
for(int i=0;i<edges[start].size();i++)
{
int next = edges[start][i];
if(visit[next]==false)
dfs(edges,next,visit,n);
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
vector<int> *edges = new vector<int>[n+1];
for (int i = 0; i < m; ++i)
{
int start,end;
cin>>start>>end;
edges[start].push_back(end);
}
// cout<<"PHASE 1"<<endl;
bool *visit = new bool[n+1];
for (int i = 0; i<=n; ++i)
{
visit[i] = false;
}
stack<int> *nodex = new stack<int>();
for (int i = 1; i<=n; ++i)
{
if(visit[i] == false)
dfs(edges,i,n,visit,nodex);
}
// cout<<"PHASE 2"<<endl;
for(int i=0;i<=n;i++)
visit[i] = false;
int count=0;
while(!nodex->empty())
{
int up = nodex->top();
nodex->pop();
// cout<<" EVERYTHING ISS FINE "<<up<<endl;
if(visit[up] ==false )
{
dfs(edges,up,visit,n);
count++;
}
// cout<<"Everrything is fine "<<up<<endl;
}
cout<<count<<endl;
}
return 0;
}
Use Fast I/O and "\n"in place of endl. This helps a lot in getting rid of TLE. For me the rest of the code seems to be fine

Simple DFS stuck in an infinite loop c++

I am trying to implement a simple DFS in C++ with n number of nodes and k number of edges.
For some reason it is getting stuck in an infinite loop:
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define MAXV 1000
void addEdge(vector<int> adj[], int u, int v){
adj[u].pb(v);
adj[v].pb(u);
}
void DFSUtil(int u, vector<int> adj[], vector<int>& visited){
visited[u] = 1;
cout << u << " ";
for(int i = 0;i<adj[u].size();i++){
if(visited[adj[u][i]] == 0){
DFSUtil(u,adj,visited);
}
}
}
void DFS(vector<int> adj[], int N){
vector<int> visited(N, 0);
for(int u = 1;u<N;u++){
if(visited[u] == 0){
DFSUtil(u,adj,visited);
cout << "\n";
}
}
}
int main(){
int n,k,m,i,u,v;
scanf("%d %d",&n,&k);
vector<int> adj[n+1];
for(i = 0;i<k;i++){
scanf("%d %d",&u,&v);
addEdge(adj,u,v);
}
// find connected components
DFS(adj,n+1);
return 0;
}
Could someone point me where am I going wrong with this code?
Sample input to test on:
4 3
1 2
2 3
1 4
After navigating through every steps, finally, I am able to find the bug.
The passed value should have been DFSUtil(adj[u][i],adj,visited); instead of DFSUtil(u,adj,visited); which actually calls the same vertex again and again and hence the infinite loop.
void DFSUtil(int u, vector<int> adj[], vector<int>& visited){
visited[u] = 1;
cout << u << " ";
for(int i = 0;i<adj[u].size();i++){
int to = adj[u][i];
if(visited[to] == 0){
DFSUtil(to, adj, visited);
}
}
}

Time out error, probably infinite loop C++

The following code works 100% using Xcode, but when i run the code using the Autograder, i got the following error Time out error, probably infinite loop C++ as showing in the image below.
Does this means that my arrays are too small?
Input:
4 6
Women Conservatives Neocons Veterans
Trump Women 1
Trump Conservatives 1
Trump Neocons 5
Women Neocons 1
Neocons Veterans 5
Conservatives Veterans 1
Output:
8
Here's My code:
#include <iostream>
#include <algorithm>
#include <string>
#include <stdlib.h>
#include <vector>
#include <ctime>
#include <map>
using namespace std;
/*map Group Name to a Integer
useful for representation of graph
*/
map <string, int> nameToNumber;
/*
adjacency matrix to represent graph
this will work since number of nodes is less
*/
int graph[301][301];
/*
recursion to find if target is reachable from src in graph
par == parent of src.. useful to keep track of visited nodes
*/
bool reachable(int src, int target, int par = -1)
{
if (src == target) return true;
bool isReachable = false;
for (int i = 0; i < 100; ++i)
{
if (i != par && graph[src][i] != 0 && reachable(i, target, src))
{
isReachable = true;
}
}
return isReachable;
}
int main()
{
int n, m;
cin >> n >> m;
// add names to map
for (int i = 0; i < n; ++i) {
string name;
cin >> name;
nameToNumber[name] = i;
}
vector <pair<int, pair<int, int>>> edges;
// input edges
for (int i = 0; i < m; ++i)
{
string u, v; int w;
cin >> u >> v >> w;
edges.push_back(make_pair(w, make_pair(nameToNumber[v], nameToNumber[u])));
}
// sort edges based in increasing weights
sort(edges.begin(), edges.end());
int cost = 0;
for (int i = 0; i < edges.size(); ++i) {
int u = edges[i].second.first;
int v = edges[i].second.second;
int w = edges[i].first;
// check if u-v edge causes cycle
if (!reachable(u, v)) {
graph[u][v] = 1;
cost += w;
}
}
cout << cost ;
return 0;
}
Everytime i run my code using the Autograder i get the following error Time out error, probably infinite loop.
CLICK HERE