Path finding using dfs and bfs - c++

my undirected graph is this:-
{0,1,1,0,0,
1,0,0,1,0,
1,0,0,1,0,
0,1,1,0,1,
0,0,0,1,0};
i want to find the path between two nodes using bfs and dfs as my assignment.
when i perform bfs i simply print the nodes which should be minimum path but it shows 01234 but i want is 0134 or 0234 and when i perform dfs it gives 01324.
my bfs code:-
#include <iostream>
#include<queue>
using namespace std;
int main(){
int matrix[5][5]={0,1,1,0,0,
1,0,0,1,0,
1,0,0,1,0,
0,1,1,0,1,
0,0,0,1,0};
//int nodes[3] = {5,6,7};
int visited[5] = {0,0,0,0,0};
int inNode,pathNode;
cout<<"Enter Initial Node: ";
cin>>inNode;
cout<<"Enter Path Node: ";
cin>>pathNode;
int traceBack[5],rec=0;
queue<int> myqueue;
myqueue.push(inNode);
int node = myqueue.front();
visited[inNode] = 1;
//cout<<node<<"\n";
while(!myqueue.empty()){
int s = myqueue.front();
myqueue.pop();
for(int i =0 ; i<5;i++){
if(matrix[s][i] == 1 && visited[i] == 0){
myqueue.push(i);
visited[i] = 1;
traceBack[rec] = i;
rec++;
}
}
}
cout<<inNode;
int j = 0;
while(traceBack[j]!=pathNode){
cout<<"->"<<traceBack[j];
j++;
}
cout<<"->"<<pathNode;
return 0;
}
my dfs code:-
#include<iostream>
using namespace std;
int visited[5]= {0,0,0,0,0};
int traceBack[5],rec=0;
int matrix[5][5]={0,1,1,0,0,
1,0,0,1,0,
1,0,0,1,0,
0,1,1,0,1,
0,0,0,1,0};
void dfs(int v){
int i;
visited[v]=1;
for(i= 0 ; i<5;i++){
if(matrix[v][i] && visited[i]==0){
traceBack[rec] = i;
rec++;
cout<<i;
dfs(i);
}
}
}
int main(){
int inNode,pathNode;
cout<<"Enter Initial Node: ";
cin>>inNode;
cout<<"Enter Path Node: ";
cin>>pathNode;
dfs(inNode);
int k=0;
while(traceBack[k]!=pathNode)
{
k++;
cout<<traceBack[k];
}
return 0;
}

The problem is that the "traceBack" is not actually tracing back. It just contains the order in which nodes were visited, which is not necessarily the path that you want.
What you need to do?
When some node s accesses another node i, then traceBack[i] = s. Why? because it says that i was accessed from s, this way every node can follow its trace back. (you also initialize traceBack[inNode] = -1 since this node was not accessed by anybody)
Now, when the algorithm is finished the following code will give you the path. (It first gets the path in reverse order and then reverses it to get the correct order)
int i = pathNode;
int path[1000];
int path_len = 0;
//this gives you the path in reverse order
while(traceBack[i] != -1){ // there is something to trace
path[path_len++] = i;
i = traceBack[i];
}
path[path_len++] = inNode; // the inNode is left out in the while loop
//printing the path in right order
for(int j = path_len - 1; j >= 0; j—-){
cout << path[j] << " -> ";
}

You problem is, for BFS, you cannot use the same method to trace back as you use for DFS. You may modify your code as follow:
while(!myqueue.empty()){
int s = myqueue.front();
myqueue.pop();
for(int i =0 ; i<5;i++){
if(matrix[s][i] == 1 && visited[i] == 0){
myqueue.push(i);
visited[i] = 1;
traceBack[i] = s;
}
}
}
So, now, traceBack contains the parent of each node. To find path from node 4 to 0:
int j = pathNode;
while(traceBack[j]!=0){
cout<<"<-"<<traceBack[j];
j++;
}
cout<<"<-"<<0;

Related

Different results during Debug and Run in C++

I'm working on a algorithm problem, and it discribed as follows:
Suppose the deep learning model is a directed acyclic graph. If operator A depends on the output of operator B, then A can be calculated after the execution of B. If there is no dependency relation, then A can be executed in parallel. Given N nodes, the information of each node contains the execution time of the node and the list of the next nodes, and the shortest execution time of the neural network is calculated. The node index starts at 0.
and here is the input example:
7
A 10 1 2 3
B 9 4 5 6
C 22
D 20
E 19
F 18
G 21
Here is my solution:
#include <bits/stdc++.h>
using namespace std;
int dfs(int nodeTime, const vector<int>& nextNodes, vector<vector<int>> NN){
// Check whether the children of the current node have children
bool is_end = true;
for (int node : nextNodes) {
if (NN[node][1] != 0){
is_end = false;
break;
}
}
//The children of the current node have no children, find the maxTime
if (is_end) {
int maxTime = 0;
for (int node : nextNodes) {
maxTime = max(node, maxTime);
}
return nodeTime + maxTime;
}
//some children of the current node have children, keep doing dfs()
else{
int maxTime = 0;
for (int nodeIdx : nextNodes) {
if (NN[nodeIdx].size() != 1){
vector<int> next;
next.assign(NN[nodeIdx].begin() + 1, NN[nodeIdx].end());
maxTime = max(maxTime, dfs(NN[nodeIdx][0], next, NN));
}
else maxTime = max(maxTime, NN[nodeIdx][0]);
}
return maxTime + nodeTime;
}
}
int str_int(const string& s){
char c[10];
strcpy(c, s.c_str());
return atoi(c);
}
int main() {
// input stage
int n;
cin >> n;
vector<vector<int>> NN;
vector<int> temp;
vector<string> stemp;
string s;
for (int i = 0; i < n; ++i) {
stemp.clear();
temp.clear();
while (cin >> s){
stemp.push_back(s);
if (getchar() == '\n') break;
}
for (int j = 1; j < stemp.size(); ++j) {
temp.push_back(str_int(stemp[j]));
}
NN.push_back(temp);
}
vector<int> initialNextNodes; //Initialize the sequence of children of the starting node
initialNextNodes.assign(NN[0].begin() + 1, NN[0].end());
int res = dfs(NN[0][0], initialNextNodes, NN);
cout << res;
return 0;
}
The right output is 40, Debug mode gives the right answer, but Run mode gives the wrong answer, I can't figure out what went wrong. I looked up the common causes of this error, probably a pointer being used without space allocated, or a variable being used without an initial value assigned. But these do not seem to be the answer to my question, can anyone help me? I would be so grateful.

Error while Compiling "|75|error: cannot convert 'std::vector<int>' to 'int'" while implementing bfs

I am implementing bfs (Breadth First Search ) for the graph , but I am getting an error while I pass the starting value of the vector to an integer, for the dfs function to perform, as in the dfs function I have passed the source of the vector, i.e the first element of the vector.
error is on the line where start is declared to v[i]
Here is the complete code
#include <iostream>
#include <vector>
#include <queue>
#include <stdio.h>
using namespace std;
vector<int> v[10];
bool visited[10];
int level[10];
int a = 0;
int arr[10];
void dfs(int s) //function should run only one time
{
queue<int> q;
q.push(s);
visited[s] = true;
level[s] = 0;
while (!q.empty())
{
int p = q.front();
arr[a] = p;
a++;
q.pop();
for (int i = 0; i < v[p].size(); i++)
{
if (visited[v[p][i]] == false) {
level[v[p][i]] = level[p] + 1;
q.push(v[p][i]);
visited[v[p][i]] = true;
}
}
}
}
int main()
{
char c;
int start; // starting element of the vector
int i = 0; // for keeping track of the parent
int countt = 0; // keep track of the no of parents
bool check;
printf("Child or Parent ?");
scanf("%c", &c);
while (countt <= 10) {
if (c == 'c') {
check = true;
int j = 0;
while (check) {
// to keep the track of the child;
scanf("%d", &v[i][j]);
j++;
}
}
if (c == 'p')
{
scanf("%d", &v[i]);
if (i == 0)
{
start = v[i];
}
i++;
countt++;
}
}
printf(" Vector input completed");
dfs(start);
printf("DFS completed, printing the dfs now ");
for (int g = 0; g <= 10; g++)
{
printf("%d", &arr[g]);
}
}
In your current code, v is an array of size 10 containing vector's. However, start is an int, so there is nothing strange in getting an error when trying to assign one to another.
I believe that you wanted v to be either an array of ints or vector of ints. In such a case you just have to declare v properly: int v[10] or vector<int> v(10).
This is general syntax: if you want to declare a vector with known size then you have to put it in (), not in []. Note that you can also fill the vector with some initial values (say zeroes) by writing vector<int> v(10, 0).
In case got you wrong and you wanted to store a graph as vector of vectors, then you can write vector<vector<int>> v(10).

How to write code for Breadth-first search in C++

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.

BinSearch fails after Bubble Sort

My program seems to be behaving oddly all of a sudden and I cannot figure out why no matter how I look.
Let's begin with the header
//inventoryData.h
//This is the second edition of inventory data, now featuring an actual description
//This header will load an array, sort it, and then be used in InventorySearch to produce parts and prices.
//by Robert Moore on [DATE]
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
class InventoryData{
//Variables
private:
int partNum[1000];
double price[1000];
int invCount;
public:
InventoryData();//Build Up
void loadArrays(); //Feed the data from the database into our arrays
void arraySort(); //Bubblesort for the array
int seqSearch(int); //Our one by one search method
int binSearch(int); //The other search
int returnpart(int); //Return Part Number
double returnPrice(int); //Return price
//Incorportate a search counter to both these searches?
//IE: bin search found [x] (completed after [y] records)
};
InventoryData::InventoryData()
{
//Load the array
invCount = 0;
for (int count = 0; count < 1000; count++)
{
partNum[count] = 0;
price[count] = 0;
}
}
void InventoryData::arraySort()
{
int counter = 0; //Used to keep track of subscripts
int temp = 0; //Used to sort subscript contents
double tempPrice = 0;
int maxSub = invCount;
int lastKnown = 0; //Used to indicate what the last swapped value was
char swap = 'Y'; //used to indicate if a swap was made or not
while (swap == 'Y')
{
swap = 'N';
counter = 0;
while (counter < maxSub){
if (partNum[counter] < partNum[counter+1])
{
//Swap the part number
temp = partNum[counter];
partNum[counter] = partNum[counter+1];
partNum[counter+1] = temp;
//Swap the price
tempPrice = price[counter];
price[counter] = price[counter+1];
price[counter+1] = tempPrice;
//Report the swap occured
swap = 'Y';
lastKnown = counter;
}
counter++;
}//End of While Loop
maxSub = lastKnown;
}//End this While Loop Too
cout<<"File sort complete."<<endl;
}
void InventoryData::loadArrays()
{
ifstream partIn;
partIn.open("masterInventory.dat");
cout<<"Loading..."<<endl;
if (partIn.is_open())
{
//Prime Read
partIn >> partNum[invCount]
>> price[invCount];
//cout<<partNum[invCount]<<" and "<<price[invCount] <<" have been loaded."<<endl;
while(!partIn.eof())
{
invCount++;
partIn >> partNum[invCount]
>> price[invCount];
// cout<<partNum[invCount]<<" and "<<price[invCount] <<" have been loaded."<<endl;
} //END While
partIn.close();
cout<<"All files loaded successfully."<<endl;
} //END IF*/
else
{
invCount = -1;
cout<<"File failed to open."<<endl;
}
//arraySort();
}
int InventoryData::seqSearch(int searchKey)
{
int index = 0;
int found = -1;
int counter = 0;
while(index < invCount)
{
counter++;
if (searchKey == partNum[index]
)
{
found = index;
index = invCount;
}
else
{
index++;
}
}
cout<<"(Sequential completed after reading "<< counter<<" files.)"<<endl;
return found;
}
int InventoryData::binSearch(int searchKey)
{
int first = 0;
int last = invCount;
int found = 0;
int mid = 0;
int counter = 0;
while (first <= last && found == 0)
{
counter++;
mid = (first + last)/2;
if (searchKey == partNum[mid] ){
found = 1;
return mid;
}
else
{
if (partNum[mid] < searchKey)
{
first = mid+1;
}
else
{
last = mid - 1;
}
}
}
if (found == 0)
{
mid = -1;
}
cout<<"(Binary completed after reading "<< counter <<" files.)"<<endl;
return mid;
}
int InventoryData::returnpart(int value)
{
return partNum[value];
}
double InventoryData::returnPrice(int value)
{
setprecision(2);
return price[value];
}
With this set up, the program loads numbers from a database (any random combination of digits and another set of "prices"), then we call the function to load, sort, and search the array, as found in the CPP file
//InventorySearch
/*This file is used to search our databases
and return a value for whatever our search may
be looking for.*/
//by Robert Moore
#include "inventoryData.h"
#include <iomanip>
int main()
{
//Declare Variable
int tempSeq = 0;
int tempBin = 0;
int search = 0;
char confirmation = 'Y';
int searchCounter = 0;
int partsFound = 0;
int partsLost = 0;
//Build Object and Load Array
InventoryData invent;
invent.loadArrays();
invent.arraySort();
//Introduction
cout<<"Welcome to Part Search."<<endl;
//Begin Loop Here
while(confirmation != 'N')
{
cout<<"Please enter a part number: ";
searchCounter++;
cin>>search;
cout<<endl;
tempSeq = invent.seqSearch(search);
if (tempSeq != -1)
{
std::cout << std::fixed;
cout<<"Sequential found part number "<<invent.returnpart(tempSeq)<< ", and it's price is "<<setprecision(2)<<invent.returnPrice(tempSeq)<<endl;
partsFound++;
}
else
{
cout<<"Sequential search failed to find part number "<<search<<endl;
partsLost++;
}
tempBin = invent.binSearch(search);
if (tempBin != -1)
{
std::cout << std::fixed;
cout<<"Binary found part number "<<invent.returnpart(tempBin)<<", and it's price is "<<setprecision(2)<<invent.returnPrice(tempBin)<<endl;
partsFound++;
}
else
{
cout<<"Binary search failed to find part number "<<search<<endl;
partsLost++;
}
cout<<"Would you like to search again? (Plese enter Y/N): ";
cin>>confirmation;
confirmation = toupper(confirmation);
}
cout<<"Today's Summary: "<<endl;
cout<<setw(5)<<"Total searches: "<<setw(25)<<searchCounter<<endl;
cout<<setw(5)<<"Total successful searches:"<<setw(15)<<(partsFound/2)<<endl;
cout<<setw(5)<<"Total unsuccessful searches:"<<setw(12)<<(partsLost/2)<<endl;
cout<<"Thank you for using Part Search. Have a nice day."<<endl;
return 0;
}
However, the output runs into the following problem: where the sequential search will scour the entire database and find our value, the binSearch will only search up to 8 values and fail. At first I thought this was due to the way the sort was loaded, but once I coded it out, it continued to fail. Worse yet, aside from adding the sort, the program function just fine prior to this.
I'm running out of ideas as to where the program is wrong, as this code worked just fine up until arraySort() was added.
In your arraySort() method, you should take note of the fact that for instance if maxSub=10, then for the part where you write
while (counter < maxSub){
if (partNum[counter] < partNum[counter+1])
{
.....
}
}
you might end up performing
if(partNum[9]<partNum[10]){
....
}
Since C++ does not perform bound checking on arrays, your code, although buggy, might end up compiling successfully, and may (or may not) produce the correct result. Thus you need to change the loop condition to
while((counter+1)<maxSub){
.....
}
Besides, your arraySort() is sorting in the Descending order, and your binSearch() has been implemented for an array sorted in ascending order. You can change either of the methods as per your requirement.
Hope this helps.
Your sorting algorithm seems faulty to me. If you are trying bubble sort, sorting implementation should be like this.
for(int counter1 = 0;counter1<invCount; ++counter1)
{
for(int counter2 = counter1+1; counter2<invCount; ++counter2)
{
if(partNum[counter1] < partNum[counter2])
{
//do swaping here.
}
}
}

Trouble with Dijkstra , finding all minimum paths

We have a problem here, we're trying to find all the shortest paths in graph from one node to another. We have already implemented dijkstra but we really dont know how to find them all.
Do we have to use BFS?
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
typedef pair <int, int> dist_node;
typedef pair <int, int> edge;
const int MAXN = 10000;
const int INF = 1 << 30;
vector <edge> g[MAXN];
int d[MAXN];
int p[MAXN];
int dijkstra(int s, int n,int t){
for (int i = 0; i <= n; ++i){
d[i] = INF; p[i] = -1;
}
priority_queue < dist_node, vector <dist_node>,greater<dist_node> > q;
d[s] = 0;
q.push(dist_node(0, s));
while (!q.empty()){
int dist = q.top().first;
int cur = q.top().second;
q.pop();
if (dist > d[cur]) continue;
for (int i = 0; i < g[cur].size(); ++i){
int next = g[cur][i].first;
int w_extra = g[cur][i].second;
if (d[cur] + w_extra < d[next]){
d[next] = d[cur] + w_extra;
p[next] = cur;
q.push(dist_node(d[next], next));
}
}
}
return d[t];
}
vector <int> findpath (int t){
vector <int> path;
int cur=t;
while(cur != -1){
path.push_back(cur);
cur = p[cur];
}
reverse(path.begin(), path.end());
return path;
}
This is our code, we believe we have to modify it but we really don't know where.
Currently, you are only saving/retrieving one of the shortest paths that you happen to find. Consider this example:
4 nodes
0 -> 1
0 -> 2
1 -> 3
2 -> 3
It becomes clear that you cannot have a single p[] value for each position, as in fact the 4th node (3) has 2 previous valid nodes: 1 and 2.
You could thus replace it with a vector<int> p[MAXN]; and work as follows:
if (d[cur] + w_extra < d[next]){
d[next] = d[cur] + w_extra;
p[next].clear();
p[next].push_back(cur);
q.push(dist_node(d[next], next));
}
else if(d[cur] + w_extra == d[next]){
p[next].push_back(cur); // a new shortest way of hitting this same node
}
You will also need to update your findpath() function as it will need to deal with "branches" resulting in several multiple paths, possibly an exponentially huge amount of paths depending on the graph. If you just need to print the paths, you could do something like this:
int answer[MAXN];
void findpath (int t, int depth){
if(t == -1){ // we reached the initial node of one shortest path
for(int i = depth-1; i >= 0; --i){
printf("%d ", answer[i]);
}
printf("%d\n", last_node); // the target end node of the search
return;
}
for(int i = p[t].size()-1; i >= 0; --i){
answer[depth] = p[t][i];
findpath(p[t][i], depth+1);
}
}
Note you'll need to do p[s].push_back(-1) at the beginning of your dijkstra, besides clearing this vector array between cases.