BFS traversal of all paths in graph using adjacency list

后端 未结 2 1666
既然无缘
既然无缘 2020-12-18 15:10

I am currently trying to traverse all paths from source to destination in a graph which uses adjacency matrix. I have been trying to do it in BFS way.Thanks for the help. I

相关标签:
2条回答
  • 2020-12-18 15:38

    Apparently it is impossible to retrieve all paths from a given source to a given terminal via Breadth-First search. Consider the following class of graphs.

    For any nonnegative integer n, let

    V := {v_1,...,v2_n}                             // inner vertices
         union
         {s, t},                                    // source and terminal
    E := { {v_i,v+2,} : i < 2n-2 }                  // horizontal edges
         union
         { {v_i,v_i+3} : i < 2n-3, i is odd }       // cross edges from top to bottom
         union
         { {v_i,v_i+3} : i < 2n-3, i is even }      // cross edges from bottom to top
         union
         { {s,v_1}, {s,v_2}, {t,v_2n-1}, {t,v_2n} } // source and terminal
    

    Informally, the graph consists out of two rows of vertices with n columns each, to the left there is a source node and to the right there is a terminal node. For each path from s to t, you can choose for each column to stay in the current row or to switch to the other row.

    In total, there are 2^n different paths from s to t, as for each column there are two possibilities to chose the row.

    On the other hand, Breadth-First search yields a runtime bound which is polynomial in the encoding length of the graph; this means that Breadth-first search, in general, cannot generate all possible paths from a given source to a given terminal. Furthermore, if the graph contains a cycle, the number of paths might be inifinite via repetition of the cycle.

    0 讨论(0)
  • 2020-12-18 15:41

    Using the following class you can run a BFS to find a single path (findPath) or find multiple paths (findAllPaths). See comments:

    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;
    
    public class AllPossiblePaths {
    
        private  boolean[] visited;
        //keep track of nodes already included in a path
        private  boolean[] includedInPath;
        private LinkedList<Integer> queue;
        private int numberOfNodes;
        private List<Integer>[] adj;
        //to find a path you need to store the path that lead to it
        private List<Integer>[] pathToNode;
    
        public AllPossiblePaths(int numberOfNodes) {
    
            this.numberOfNodes = numberOfNodes;
            adj = new ArrayList[numberOfNodes];
            pathToNode = new ArrayList[numberOfNodes];
    
            for (int i = 0; i < numberOfNodes; i++) {
                adj[i] = new ArrayList<>();
            }
        }
    
        // add edge from u to v
        public AllPossiblePaths addEdge(int from, int to) {
            adj[from].add(to);
            //unless unidirectional: //if a is connected to b
            //than b should be connected to a
            adj[to].add(from);
            return this; //makes it convenient to add multiple edges
        }
    
        public void findPath(int source, int destination) {
    
            System.out.println("------------Single path search---------------");
            initializeSearch(source);
    
            while (!queue.isEmpty()) {
                // Dequeue a vertex from queue and print it
                int src = queue.poll();
                visited[src] = true;
    
                if (src == destination) {
                    System.out.println("Path from "+source+" to "
                            + destination+ " :- "+ pathToNode[src]);
                    break; //exit loop if target found
                }
    
                Iterator<Integer> i = adj[src].listIterator();
                while (i.hasNext()) {
                    int n = i.next();
                    if (! visited[n] && ! queue.contains(n)) {
                        queue.add(n);
                        pathToNode[n].addAll(pathToNode[src]);
                        pathToNode[n].add(src);
                    }
                }
            }
        }
    
        public void findAllpaths(int source, int destination) {
    
            System.out.println("-----------Multiple path search--------------");
            includedInPath = new boolean[numberOfNodes];
            initializeSearch(source);
            int pathCounter = 0;
    
            while(! allVisited() && !queue.isEmpty()) {
    
                while (!queue.isEmpty()) {
                    // Dequeue a vertex from queue and print it
                    int src = queue.poll();
                    visited[src] = true;
    
                    if (src == destination) {
    
                        System.out.println("Path " + ++pathCounter + " from "+source+" to "
                                + destination+ " :- "+ pathToNode[src]);
                        //mark nodes that are included in the path, so they will not be included
                        //in any other path
                        for(int i=1; i < pathToNode[src].size(); i++) {
                            includedInPath[pathToNode[src].get(i)] = true;
                        }
                        initializeSearch(source); //initialize before restarting
                        break; //exit loop if target found
                    }
    
                    Iterator<Integer> i = adj[src].listIterator();
                    while (i.hasNext()) {
                        int n = i.next();
                        if (! visited[n] && ! queue.contains(n)
                                && ! includedInPath[n] /*ignore nodes already in a path*/) {
                            queue.add(n);
                            pathToNode[n].addAll(pathToNode[src]);
                            pathToNode[n].add(src);
                        }
                    }
                }
            }
        }
    
        private void initializeSearch(int source) {
    
            queue = new LinkedList<>();
            queue.add(source);
            visited = new boolean[numberOfNodes];
            for (int i = 0; i < numberOfNodes; i++) {
                pathToNode[i]= new ArrayList<>();
            }
        }
    
        private boolean allVisited() {
    
            for( boolean b : visited) {
                if(! b ) return false; 
            }
            return true;
        }
    }
    

    For testing it, consider this graph:

    Run test:

    public static void main(String[] args){
    
        AllPossiblePaths app = new AllPossiblePaths(6);
        app.addEdge(0, 4)
        .addEdge(0, 1)
        .addEdge(1, 2)
        .addEdge(1, 4)
        .addEdge(4, 3)
        .addEdge(2, 3)
        .addEdge(2, 5)
        .addEdge(3, 5);
    
        app.findPath(0,5);
        app.findPath(5,0);
        app.findAllpaths(0,5);
    }
    

    output:

    0 讨论(0)
提交回复
热议问题