1

I am trying to implement a simple Dfs path finding for a problem in which I have to print the very first path I encountered and nothing if no path is found. I was able to do it with Recursion but i am having trouble with the iterative version.

here is my code :

#include <iostream>
#include <stack>
#include <map>
using namespace std;

void PrintDFSpath(int **a, int *visited, int start, int end, int v)
{
    map<int, int> parentMap;
    stack<int> s;
    s.push(start);

    while (!s.empty())
    {
        int currEle = s.top();
        visited[currEle]=1;
        s.pop();
        if (currEle == end)
        {
            break;
        }

        for (int i = v - 1; i >= 0; i--)
        {
            if (a[currEle][i] == 1 && !visited[i] && i != currEle)
            {
                if( !parentMap.count(i) )
                    parentMap[i] = currEle;
                s.push(i);
                visited[i] = 1;
            }
        }
        if (s.empty())
        {
            return;
        }
    }
    int i = end;
    cout<<end<<" ";
    while (i != start)
    {
        cout<<parentMap[i]<<" ";
        i = parentMap[i];
    }
}

int main()
{
    int v, e;
    cin >> v >> e;
    int **a = new int *[v];

    for (int i = 0; i < v; i++)
    {
        a[i] = new int[v];
        for (int j = 0; j < v; j++)
            a[i][j] = 0;
    }
    int x, y;
    for (int i = 0; i < e; i++)
    {
        cin >> x >> y;
        a[x][y] = 1;
        a[y][x] = 1;
    }

    int v1, v2;
    cin >> v1 >> v2;

    int *visited = new int[v];
    for (int j = 0; j < v; j++)
        visited[j] = 0;

    PrintDFSpath(a, visited, v1, v2, v);
    return 0;
}

I am using an adjacency matrix here.

I have already implemented some of the things that I found on StackOverflow such as the map

Also, the get the same path as that in recursive order I am inserting the children into the stack in rev order.

Here is the Problem statement

Given an undirected graph G(V, E) and two vertices v1 and v2(as integers),
find and print the path from v1 to v2 (if exists).
Print nothing if there is no path between v1 and v2.
Find the path using DFS and print the first path that you encountered.

V is the number of vertices present in graph G and vertices are numbered from 0 to V-1.
E is the number of edges present in graph G.

Print the path in reverse order. That is, print v2 first, then intermediate vertices and v1 at last.

Input schema :

Line 1: Two Integers V and E (separated by space)
Next E lines: Two integers a and b, denoting that there exists an edge between vertex a and vertex b (separated by space)
Line (E+2): Two integers v1 and v2 (separated by space)

I am thinking the issue is coming from the following statement.

if (currEle == end)
{
    break;
}

but I can't figure out how to go about correcting it. Plz suggest something

The test case :
7 8
0 1
1 2
4 5
6 5
1 6
1 2
2 3
0 3
0 3

output : 3 2 1 0

ASHUTOSH SINGH
  • 131
  • 1
  • 13
  • 3
    If you have some input which causes the incorrect output, then it's easy to use a debugger to step through your code statement by statement while monitoring variables and their values to see when things start to go wrong. – Some programmer dude Sep 08 '20 at 15:46
  • 3
    You really should be using `std::vector`: This `int **a = new int *[v];`-- Replace this with `std::vector> a(v, std::vector(v));`. Not only does that take care of the memory leak, it also initializes all of the items to 0. The same thing here: `int *visited = new int[v];` could be `std::vector visited(v);` – PaulMcKenzie Sep 08 '20 at 15:49
  • 1
    Also, if you have the test case already, put the data directly in the code. There is no need for `cin` or any input statements. – PaulMcKenzie Sep 08 '20 at 15:50
  • @PaulMcKenzie will do the vector changes I was just trying to use minimum STL and I forgot the delete statements but definitely vector is the best to solve this. Also this the test case that failed there are many test cases which is why I cant hardcode it. – ASHUTOSH SINGH Sep 08 '20 at 16:00
  • @ASHUTOSHSINGH -- If that is a test case that fails, put that case in the code. All you need is just one failing case. In other words, set `v` and `e` directly, set the position in the vector to the 1, etc. Then not only is it easier for other s to simply take your code, compile it, and run it, you now can fix without having to type in the data over and over again. – PaulMcKenzie Sep 08 '20 at 16:02
  • ...also, people here can reproduce it. In other words, you have the required [mcve]. However, use a debugger to step through the code, it's an important skill to learn and you might as well do that now. As a new user here, also take the [tour] and read [ask]. – Ulrich Eckhardt Sep 08 '20 at 18:05

1 Answers1

1

Basically, you get a code that solves your testcase example, by removing the following code lines from your inner for loop:

if( !parentMap.count(i) )

and

visited[i] = 1;

In your code, the parentMap registers the first occurrence of a path from the currently processed element to its children. In order to mimic the recursive DFS behavior, parentMap should register the path from the current element to its parent. By overriding an existing map element when you encounter a new path that was not yet visited, you get the desired data.

The visited collection should contain the elements that you already processed. If you add children to visited within the inner for loop, you mark them as processed, when they are only enqueued for processing at some point in the future. Operating on a collection that doesn't fulfil its contract is almost always a bad idea.

grek40
  • 13,113
  • 1
  • 24
  • 50