BFS using deque - c++

Really having trouble figuring out how to fix my code. I know there are obviously errors since it isn't running, but I'm unsure of what exactly they are, or how to go about fixing them. Any help/insight would be extremely appreciated. Thank you!!
struct vertices
{
int value;
int parent;
int visited;
int distance;
};
int BFS(vertices *v, int **adj_matrix, int num_nodes)
{
int target;
int cur_v = 0;
bool found = false;
int steps = 0;
cin >> target >> num_nodes;
adj_matrix [num_nodes][num_nodes];
deque<int> q;
for(int i = 0; i < num_nodes; i++)
{
v[i].visited = 0;
v[i].distance = INFINITY;
v[i].parent = 0;
v[1].visited = 1;
v[i].distance = 0;
q.push_front(v[1].value);
while(!q.empty())
{
cur_v = q.front();
q.pop_back();
v[cur_v].visited = 1;
for(int n=0; n< num_nodes; n++)
{
if(adj_matrix[cur_v][i] == n)
{
if(v[n].visited == 0)
{
v[n].visited = 1;
v[n].distance = ((v[cur_v].distance)+1);
v[n].parent = cur_v;
q.push_front(v[n].value);
steps ++;
}
}
}
}
}
return steps;
}
int main()
{
int target;
int num_nodes;
cin >> target;
cin >> num_nodes;
vertices *v = new vertices[num_nodes];
int **adj_matrix [num_nodes][num_nodes];
for(int i=0; i < num_nodes; ++i)
{
int node;
int value;
cin >> node >> value;
int num_edges;
cin >> num_edges;
for(int j=0; j<num_edges;++j)
{
int other_node;
cin >> other_node;
**adj_matrix[node][other_node] = 1;
**adj_matrix[other_node][node] = 1;
}
}
}

The first obvious error is that you are using the wrong data
structure. When you are implementing known concepts like matrix,
BFS, you need to spend a good amount of time to think about how to
implement inputs , outputs, data structures from the algorithm.
Some people like to use std::vector<std::vector<int>> for matrices. I almost always uses std::vector<int> for matrix data.
Second error is that you are mutating the algorithm. That thing is not BFS. It is not obvious at first.
You call multiple instance of BFS inside you BFS implementation. Using the same input vertices, whose elements are being modified. At the next loop, you dont start with a clean state.
You are flattening the algorithm, removing abstractions. What if you now have to use a adjency list? You have to modify the whole thing.
Third obvious error is coding style. You didnt do such a bad job because the vertices structure is self explanatory
I had to highlight all instances of cur_vto realizes that it stands for current vertex.
Using n for a counter is not a great idea.
Taking input inside the algorithm implementation is a big nono.

Related

Finding the diameter of a tree using double DFS in C++

I'm attempting a problem on SPOJ where I'm supposed to find the longest path between any two nodes in a tree. The input consists of the number of testcases t, the number of nodes n, followed by n-1 edges given by "a b l", with a referring to node 1, b referring to node 2, and l referring to the length of the edge. I tried using the double dfs method, performing dfs on node 1 first to find the longest possible path beginning from node 1. Afterwards, I perform dfs on the node furthest away from node 1, finding the longest possible distance. Unfortunately, my code is wrong and I'm not sure why at all, and i'm hoping someone could help me out. Thanks in advance!
EDIT: Forgot to mention that I did manage to solve the problem using double BFS. I wanted to try using DFS to solve it as well because DFS is supposedly easier to implement than BFS, but using DFS gives me the wrong answer.
#include <bits/stdc++.h>
using namespace std;
vector<pair<int, int>> adj[50001];
bool visited[50001] = {0};
int maxdist = -1, maxnode = -1;
void dfs(int node, int d)
{
visited[node] = 1;
if (d > maxdist)
{
maxdist = d;
maxnode = node;
}
for(auto u: adj[node])
{
if(!visited[u.first])
{
dfs(u.first, d+u.second);
}
}
return;
}
int main()
{
int t;
cin >> t;
while(t--)
{
int n;
cin >> n;
for (int i = 0; i < n-1; i++)
{
int a, b, l;
cin >> a >> b >> l;
adj[a].push_back(make_pair(b, l));
adj[b].push_back(make_pair(a, l));
}
dfs(1, 0);
for(int i = 1; i <= n; i++)
{
visited[i] = 0;
}
dfs(maxnode, 0);
cout << maxdist << endl;
}
}
Not sure if this will make it work, but you are sharing adj[] and visited[] between different test cases, make sure to clean them up before a new test case.

C++ Counting inversions in array, Fatal Signal 11 (BIT)

I was given this challenge in a programming "class". Eventually I decided to go for the "Binary Indexed Trees" solution, as data structures are a thing I'd like to know more about. Implementing BIT was somewhat straight forward, things after that - not so much. I ran into "Fatal Signal 11" when uploading the solution to the server, which, from what I've read, is somewhat similar to a Null pointer exception. Couldn't figure out the problem, decided to check out other solutions with BIT but stumbled upon the same problem.
#include<iostream>
using namespace std;
/* <BLACK MAGIC COPIED FROM geeksforgeeks.org> */
int getSum(int BITree[], int index){
int sum = 0;
while (index > 0){
sum += BITree[index];
index -= index & (-index);
}
return sum;
}
void updateBIT(int BITree[], int n, int index, int val){
while (index <= n){
BITree[index] += val;
index += index & (-index);
}
}
/* <BLACK MAGIC COPIED FROM geeksforgeeks.org> */
int Count(int arr[], int x){
int sum = 0;
int biggest = 0;
for (int i=0; i<x; i++) {
if (biggest < arr[i]) biggest = arr[i];
}
int bit[biggest+1];
for (int i=1; i<=biggest; i++) bit[i] = 0;
for (int i=x-1; i>=0; i--)
{
sum += getSum(bit, arr[i]-1);
updateBIT(bit, biggest, arr[i], 1);
}
return sum;
}
int main(){
int x;
cin >> x;
int *arr = new int[x];
for (int temp = 0; temp < x; temp++) cin >> arr[temp];
/*sizeof(arr) / sizeof(arr[0]); <-- someone suggested this,
but it doesn't change anything from what I can tell*/
cout << Count(arr,x);
delete [] arr;
return 0;
}
I am quite stumped on this. It could be just some simple thing I'm missing, but I really don't know. Any help is much appreciated!
You have condition that every number lies between 1 and 1018. So, your biggest number can be 1018. This is too much for the following line:
int bit[biggest+1];

Implementing a Graph DFS in C++, pointers issue

Sorry in advance, but some variable names and such have strange names, as I am not a native English speaker, I am also pretty new to programming.
So, I was doing a project with graphs topology sorting and similar, but I can't get DFS to work, I know that I am probably losing data because of usage of pointers in there(?), but I won't be using this adjacency list in my program any further anyway. The problem is just to get right result which in this case is when the vertex was entered (d[]) and left (f[]) but while in recursion my pointers go crazy, sometimes when I go back in recurrence (and apparently nothing else happens), I think at least because it's the first time I am using debugging function. I am sitting at this for like 8 hours already (not my first problem, but I managed to solve some, that's why code looks so ugly), and I was sitting with this debugger and didn't make any progress in over an hour, so I decided to ask, my first time using this website, I hope you can help me, and when I am a bit better I will definitely return the favor, here's the code:
#include <iostream>
#include <cstdlib>
#include <time.h>
struct m_sasiedztwa
{
int s;
int** m;
m_sasiedztwa(int a,float b) : s(a)
{
m = new int*[s];
for(int i = 0; i < s; ++i) m[i] = new int[s];
for(int j=0; j<s; ++j)
for(int k=0; k<s; ++k) if(j!=k) m[j][k]=((rand()%100)>(100*b))? 0 : 1; else m[j][k]=0;
}
~m_sasiedztwa()
{
delete[] m;
}
};
struct lista
{
int key;
lista *next;
};
struct l_nast
{
int s;
lista** arr;
l_nast(int** m, int a) : s(a)
{
lista *curr,*prev;
arr = new lista*[s];
for(int i=0;i<s;++i)
{
arr[i] = new lista;
curr = arr[i];
prev=curr;
prev->key=-1;
for(int j=0;j<s;++j)
{
if(m[i][j]==1) {curr->next= new lista;curr->key=j;prev=curr;curr=curr->next;}
}
prev->next=nullptr;
}
}
~l_nast() {delete[] arr;}
};
//Here is the issue
bool *Nowy;
int c;
int* d,*f;
void DFS(int j,l_nast l_a)
{
Nowy[j]=false;
d[j]=c++;
std::cout<<"Am I here yet..."<<j<<" "<<c<<std::endl;
while((l_a.arr[j]!=nullptr)&&(l_a.arr[j]->key!=-1))
{
std::cout<<"checking "<<(l_a.arr[j]->key)<<"...\n";
if(Nowy[l_a.arr[j]->key])
{
DFS(l_a.arr[j]->key,l_a);
}
if(l_a.arr[j]->next!=nullptr) //And I think this may be the problem, but I honestly don't know
l_a.arr[j]=l_a.arr[j]->next;
else break;
}
f[j]=c++;std::cout<<"Yohoo!"<<j<<" "<<c<<std::endl;
}
//Untill there
using namespace std;
int main()
{
srand (time(NULL));
for(int q=5; q<6; q+=5)
{
m_sasiedztwa a = m_sasiedztwa(q, 0.2);
m_sasiedztwa b = m_sasiedztwa(q, 0.4);
l_nast l_a = l_nast(a.m,q);
l_nast l_b = l_nast(b.m,q);
/*
for(int i=0; i<q; ++i)
{
for(int j=0; j<q; ++j)
{
cout << a.m[i][j] << " ";
}
cout<<endl;
}
cout<<endl;
*/
Nowy = new bool [q];
d = new int [q];
f = new int [q];
c=0;
for (int i = 0; i < q; i++)
Nowy[i] = true;
/*for(int qq=0;qq<q;qq++)
while((l_a.arr[qq]!=nullptr))
{
cout<<l_a.arr[qq]->key<<endl;
l_a.arr[qq]=l_a.arr[qq]->next;
}
*/
for(int j=0;j<q;j++)
{
if(Nowy[j]) DFS(j,l_a);
}
a.~m_sasiedztwa();
b.~m_sasiedztwa();
l_a.~l_nast();
l_b.~l_nast();
}
return 0;
}
As I said it's not pretty, sorry for troubling you, again what I need help with is to get function DFS to properly result with d[] which is a table if integers which indicate when the vertex was visited, and f[] - table when the vertex was taken from the stack, just ordering 1,2,3..., the problem is - it breaks in the middle, sometimes it does like 7/10 sometimes just 2/10 and it breaks, of course, it will have to work for bigger graphs as well. The pointers are lost and it tries to check Nowy[some big number there] and program crashes.
So, I used struct badly and made many mistakes, thanks to some comments I decided to use vector of vectors for adj matrix and vector of forward_list for adj list Here is what changed m_sasiedztwa struct
struct m_sasiedztwa
{
int s;
std::vector<std::vector<int>> m;
m_sasiedztwa(int a,float b) : s(a), m(s, std::vector<int>(s,0))
{
for(int j=0; j<s; ++j)
for(int k=0; k<s; ++k)
if(j!=k)
m[j][k]=((rand()%100)>(100*b))? 0 : 1;
}
};
l_nast struct:
struct l_nast
{
int s;
std::vector<std::forward_list<int>> arr;
l_nast(std::vector<std::vector<int>> m, int a) : s(a), arr(s)
{
for(int i=0;i<s;++i)
{
auto it = arr[i].before_begin();
for(int j=0;j<s;++j)
{
if(m[i][j]==1) {it = arr[i].emplace_after(it,j);}
}
}
}
};
and the DFS:
void DFS(int j,l_nast l_a)
{
Nowy[j]=false;
d[j]=c++;
std::cout<<"Visiting "<<j<<"as "<<c<<std::endl;
auto x=l_a.arr[j].begin();
for(auto& x: l_a.arr[j])
{
if(Nowy[x])
{
DFS(x,l_a);
}
}
f[j]=c++;std::cout<<"Leaving "<<j<<"as "<<c<<std::endl;
}

Boolean array getting unexpected default values

I wrote the following C++ program to implement breadth first search to solve this problem of finding shortest path for all the nodes from the source.
#include<iostream>
#include<vector>
#include<string.h>
#include<queue>
using namespace std;
int main()
{
int test;
cin >> test;
while(test--)
{
int m,n,source;
cin >> n >> m;
bool visited[n+1];
int dist[1001];
queue<int> q;
memset(dist, -1, sizeof(dist));
vector<int> adj[1001];
for(int i = 0; i < m; i++)
{
int a, b;
cin >> a >> b;
adj[a].push_back(b);
adj[b].push_back(a);
}
cin >> source;
dist[source] = 0;
visited[source] = true;
q.push(source);
while(q.size())
{
int v = q.front();
q.pop();
for(int i : adj[v])
{
if(!visited[i])
{
q.push(i);
dist[i] = dist[v] + 6;
visited[i] = true;
}
}
}
for(int i = 1; i <= n; i++)
{
if(i != source)
{
cout << dist[i] << " ";
}
}
cout << "\n";
}
}
It works well if the value of test is 1, but when the value is 2 or more, some values of the boolean array "visited" become 1 in the second and later iterations. I do not understand why and how it happens as I declare the boolean array in every iteration and the default value for its elements is 0. Can somebody please explain this.
I declare the boolean array in every iteration and the default value for its elements is 0.
No, it's not 0. There are no default values for C++ simple types. My bet is you propably get some random values, as your array isn't initialised automatically.
You aren't initialising the array, and local arrays are not zero initialised, so explicit initialisation is needed.

RunTime Error - Tree isomorphism

In this code I want to check whether two trees are isomorphic or not.
The algorithm that I've used is to get two strings with the help of DFS algorithm, sorting them and then comparing them.
This code works in visual studio 2010 but when I try to submit in UVA online judge I keep getting the Run Time Error and since I'm not a professional programmer I can't understand why.
I was also trying to optimize my code so I used short instead of int and scanf - printf instead of cin and cout.
I would appreciate some help on how to fix my code and also how to optimize it.
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef vector<short> vi;
typedef vector<vi> vvi;
short V=0; // number of vertices for the trees.
string str;
string strrr;
short max1=0;
short max2=0;
short temp=0;
short GetDeg1(vvi t1, short n1) // for the first tree
{
vi deg(n1+1);
for( short i=1; i<n1+1 ;i++) // to make a vector named deg that has the degree of each vertex
{
deg[i]= t1[i].size();
if(deg[i]>max1)
{
temp=i; // temp has the index of the vertex with the maximum degree
max1=deg[i];
}
}
return temp;
}
short GetDeg2(vvi t2, short n2) // for the second tree
{
vi deg(n2+1);
for( short i=1; i<n2+1 ;i++)
{
deg[i]= t2[i].size();
if( deg[i]>max2)
{
temp=i;
max2=deg[i];
}
}
return temp;
}
string DFSUtil(vvi t ,short v, bool visited[])
{
visited[v] = true; // Mark the current node as visited
// Recur for all the vertices adjacent to this vertex
vector<string >strnode ;
for(short i = 0 ; i< (short)(t[v].size() ); ++i)
{
if(!visited[t[v][i]])
{ string a;
a = DFSUtil(t, t[v][i], visited);
strnode.push_back(a) ;
}
}
sort (strnode.begin(), strnode.end());
str="(";
for(short t=0; t< (short)(strnode.size()); t++)
str+= strnode[t];
str+=")";
return str;
}
string DFS(vvi t, short v)
{
bool *visited = new bool[V+1]; // Mark all the vertices as not visited
for(short i = 1; i < V+1; i++)
visited[i] = false;
strrr= DFSUtil(t, v, visited); // Call the recursive helper function to print DFS traversal
return strrr;
}
int main()
{
while(cin>>V)
{
max1=0;
max2=0;
temp=0;
string str1;
string str2;
strrr.clear();
str1.clear();
str2.clear();
str.clear();
short v1 ;
short v2;
vvi Tree1(V+1);
for( short i=0; i<V-1; i++)
{
scanf("%d",&v1);
scanf("%d",&v2);
Tree1[v1].push_back(v2);
Tree1[v2].push_back(v1);
}
vvi Tree2(V+1);
for( short i=0; i<V-1; i++)
{
scanf("%d",&v1);
scanf("%d",&v2);
Tree2[v1].push_back(v2);
Tree2[v2].push_back(v1);
}
cout<<endl;
short temp1=0;
short temp2=0;
temp1= GetDeg1(Tree1, V);
temp=0;
temp2= GetDeg2(Tree2, V);
str1=DFS(Tree1, temp1);
str.clear();
strrr.clear();
str2=DFS(Tree2, temp2);
if( str1.compare(str2) == 0)
printf("S\n");
else
printf("N\n");
}
return 0;
}