简体   繁体   中英

Find all paths in a Tree represented as Graph, From any node to any node. ( Only in downward direction )

Given edges

Edges: { {1,2},
         {1,3},
         {3,4},
         {3,5},
         {5,6}};

Find all possible paths from any node to any node ( Note moves only downwards from root node ).
Expected Output:

1->2
1->3
1->3->4
1->3->5
1->3->5->6
3->4
3->5
5->6
3->5->6

I've written code for this. But I'm only able to get: 1->2, 1->3, 3->4, 3->5, 5->6.

Code: https://leetcode.com/playground/bEp484tr

static void dfs(int source){
    Stack<Integer> stack = new Stack<>();
    HashSet<Integer> visited = new HashSet<>();
    int currVertex;
    String path = "";
            
    stack.push(source);
    visited.add(source);
    
    while(!stack.isEmpty()){
        currVertex = stack.pop().intValue();
        path += currVertex;
        
        if(!adjList.containsKey(currVertex)){
            continue;
        }
        
        // Visiting its neighbours
        for(int neighbour : adjList.get(new Integer(currVertex))){
            if(!visited.contains(new Integer(neighbour))){
                path += neighbour;
            
                visited.add(neighbour);
                stack.push(neighbour);
                
                System.out.println(path);
                
                // Undo
                path = path.substring(0, path.length() - 1);
                
            }
        }
        
        path = "";
    }
}

Could you please help me to understand where I've gone wrong, why only the 2 digits output is getting printed?
Also, How do I handle the case for 3->5->6 ? This is the case where the parent node is not the root node.

The problem is that you use one path for all traversals, and set it to the empty string in each iteration of the the main BFS loop.

Instead, a path should be proper to how a node was reached, which you should tie with the vertex you have on the stack. There are several ways to do this. One is to store the paths on the stack -- not only the final vertex of that path.

It is also problematic that you assume that a vertex is only represented by one single character when you remove the last vertex from the path string. Instead of representing a path as a string, I would suggest representing it as an array list.

Finally, visited should not prevent that you visit a node again during this BFS traversal, since you really want to produce all alternative paths to the same node -- not just one. You can really do this without visited , and instead verify that a neighboring node is not already in the current path.

Here is the corrected code:

static void dfs(int source){
    Stack<ArrayList<Integer>> stack = new Stack<>();
    ArrayList<Integer> path = new ArrayList<Integer>();
    path.add(source);
    stack.push(path);
    
    while(!stack.isEmpty()){
        path = stack.pop();
        int currVertex = path.get(path.size() - 1);
        
        if(!adjList.containsKey(currVertex)){
            continue;
        }
        
        // Visiting its neighbours
        for(int neighbour : adjList.get(currVertex)){
            if(!path.contains(neighbour)){ // Not a cycle
                ArrayList<Integer> newPath = new ArrayList<Integer>();
                newPath.addAll(path);
                newPath.add(neighbour);
                stack.push(newPath);
                for (int vertex : newPath) {
                    System.out.print(vertex + " ");
                }
                System.out.println();
            }
        }
    }
}

I can offer another variant of the solution of your problem, using twice the algorithm Depth first search in various contexts.

Edges:
{{1,2}, {1,3}, {3,4}, {3,5}, {5,6}};
    1
   / \
  2   3
     / \
    4   5
         \
          6
Expected Output:
1->2
1->3
1->3->4
1->3->5
1->3->5->6
3->4
3->5
5->6
3->5->6

Here is the solution:

#include <bits/stdc++.h>
using namespace std;
const int maximumSize=10;
int vertices, edges;
vector<int> visited0(maximumSize, 0);
vector<vector<int>> visited1(maximumSize, vector<int>(maximumSize, 0));
vector<int> graph[maximumSize];
vector<int> distancesFromBottom(maximumSize, 0);
vector<string> graphPaths;
string path;
template<class Type>
void showContent1D(Type& input)
{
    for(int i=0; i<input.size(); ++i)
    {
        cout<<input[i]<<", ";
    }
    return;
}
void createGraph()
{
    cin>>vertices>>edges;
    int vertex0, vertex1;
    for(int i=1; i<=edges; ++i)
    {
        cin>>vertex0>>vertex1;
        graph[vertex0].push_back(vertex1);
        graph[vertex1].push_back(vertex0);
    }
    return;
}
void dfs0(int current, int previous)
{
    if(visited0[current]==1)
    {
        return;
    }
    visited0[current]=1;
    for(int next : graph[current])
    {
        if(next==previous)
        {
            continue;
        }
        dfs0(next, current);
        distancesFromBottom[current]=max(distancesFromBottom[current], distancesFromBottom[next]+1);
    }
    return;
}
void dfs1(int root, int current, int previous)
{
    if(visited1[root][current]==1)
    {
        return;
    }
    if(distancesFromBottom[root]==0)
    {
        return;
    }
    visited1[root][current]=1;
    if(root==current)
    {
        path.append(to_string(root));
        path.append("->");
    }
    else
    {
        if((distancesFromBottom[current]!=0) && (distancesFromBottom[root]>distancesFromBottom[current]))
        {
            path.append(to_string(current));
            path.append("->");
        }
    }
    for(int next : graph[current])
    {
        if(next==previous)
        {
            continue;
        }
        if(distancesFromBottom[current]<distancesFromBottom[next])
        {
            continue;
        }
        if(distancesFromBottom[root]<distancesFromBottom[current])
        {
            continue;
        }
        path.append(to_string(next));
        graphPaths.push_back(path);
        path.pop_back();
    }
    for(int next : graph[current])
    {
        if(next==previous)
        {
            continue;
        }
        dfs1(root, next, current);
    }
    return;
}
void solve()
{
    createGraph();
    dfs0(1, 0);
    for(int vertex=1; vertex<=vertices; ++vertex)
    {
        path.clear();
        dfs1(vertex, vertex, 0);
    }
    cout<<"graphPaths <- "<<endl;
    showContent1D(graphPaths);
    return;
}
int main()
{
    solve();
    return 0;
}

Here is the result:

1->2, 1->3, 1->3->4, 1->3->5, 1->3->5->6, 3->4, 3->5, 3->5->6, 5->6, 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM