简体   繁体   English

给定一个有向图,找出两个节点之间是否存在路由

[英]Given a directed graph, find out whether there is a route between two nodes

I'm trying to solve this problem and i'm fairly new to graphs. 我正在尝试解决这个问题,我对图形还很陌生。 I tried BFS to figure this out but i'm not getting the right answer. 我试图通过BFS来解决这个问题,但是我没有得到正确的答案。

What am i doing wrong? 我究竟做错了什么? Also, is there a better way of doing this, other than the approach i am using. 另外,除了我使用的方法之外,还有没有更好的方法可以做到这一点。

public static boolean isThereARoute(int[][] graph ,gNode n1 , gNode n2 ) {
    // where can we move? - anywhere where the value of x and y is 1 - else can't move
    // Start with node 1 and then traverse either BFS or DFS to see if the n2 is in the path anywhere

    // using BFS.

    //mark the ones where we can move as true
    boolean[][] canMove= new boolean[graph.length][graph[0].length]; 
    for(int i = 0;i<canMove.length;i++){
        for(int j =0;j<canMove[0].length;j++){
            if(graph[i][j]==-1){
                canMove[i][j] = false;
            }else{
                canMove[i][j] = true;
            }
        }
    }



    // create a queue
    Deque<gNode> queue = new LinkedList<gNode>();
    // insert the first node into the queue
    queue.add(n1);


    while(!queue.isEmpty()){
        gNode top = queue.poll();
        int x = top.x1;
        int y = top.y1;
        // only check the ones where we can go

        if( ( top.x1>=0 && top.x1<= graph.length-1) && (top.y1>=0 && top.y1<= (graph[0].length-1)) ){

            if(canMove[top.x1][top.y1]){

                if((top.x1 == n2.x1) && (top.y1 == n2.y1)){
                    // found our node;
                    return true;
                }

                // else haven't found any - add the nodes to the queue // allowed diagonals as well// therefore for each node 
                // there can be 8 neighbors
                queue.add(new gNode(x-1,y));
                queue.add(new gNode(x,y-1));
                queue.add(new gNode(x+1,y));
                queue.add(new gNode(x,y+1));
                queue.add(new gNode(x-1,y-1));
                queue.add(new gNode(x-1,y+1));
                queue.add(new gNode(x+1,y+1));
                queue.add(new gNode(x+1,y-1));

            }

        }

    }

    return false;
}

And for the check- 对于检查-

        int[][] graphD = new int[][]{

        {-1, 1,-1,-1,-1},
        {-1,-1, 1,-1,-1},
        {-1,-1, 1, 1,-1},
        {-1,-1,-1,-1,-1},
        { 1,-1, 1,-1,-1}
    };

    ArrayList<gNode> nodes = new ArrayList<gNode>();
    nodes.add(new gNode(0,0));//node A
    nodes.add(new gNode(1,1)); // node B
    nodes.add(new gNode(2,2)); // node C
    nodes.add(new gNode(3,3)); // node D
    nodes.add(new gNode(4,4)); // node E

    /**
     *  A->b
     * B->C
     * C->C
     * C->D
     * E-A
     * 
     */ 

    System.out.println(" is A -B connected?"+isThereARoute(graphD, nodes.get(0), nodes.get(1)));
    System.out.println(" is A -D connected?"+isThereARoute(graphD, nodes.get(0), nodes.get(3)));
    System.out.println(" is C -A connected?"+isThereARoute(graphD, nodes.get(3), nodes.get(0)));
    System.out.println(" is A -E connected?"+isThereARoute(graphD, nodes.get(0), nodes.get(4)));
    System.out.println(" is C -C connected?"+isThereARoute(graphD, nodes.get(2), nodes.get(2)));

I would say that BFS is the right algorithm to apply here, so it's just a problem with your BFS code. 我会说BFS是在这里应用的正确算法,因此这只是您的BFS代码的问题。 It looks like you're confused about how graphs are represented in an Adjacency Matrix . 您似乎对图在邻接矩阵中的表示方式感到困惑。

            if((top.x1 == n2.x1) && (top.y1 == n2.y1)){
                // found our node;
                return true;
            }

This is checking if a specific entry in the adjacency matrix (an edge) has been reached, but you're just supposed to be checking if a given node is reachable. 这是在检查是否已到达邻接矩阵(边)中的特定条目,但是您只是要检查给定节点是否可到达。

You should change your gNode representation to use a single index (or just drop it and use an int instead), and do your BFS from the first node based off the adjacency matrix values. 您应该更改gNode表示形式以使用单个索引(或者只是删除它并使用int代替),并根据邻接矩阵值从第一个节点开始执行BFS。

If you need some additional help with understanding the algorithm / data structures, this page seems like a good reference: Adjacency matrices, BFS, DFS . 如果您在了解算法/数据结构方面需要其他帮助,则此页面似乎是不错的参考: 邻接矩阵,BFS,DFS

I'm not good at debugging more than 10-20 lines of code if I'm not really familiar with the language. 如果我不太熟悉该语言,则我不擅长调试10-20行以上的代码。 However, I can tell you that there is a better overall approach to tell if there is a path between two nodes x and y, instead of just BFS or DFS starting from x. 但是,我可以告诉您,有一种更好的整体方法来判断两个节点x和y之间是否存在路径,而不是仅仅从x开始的BFS或DFS。 Namely, you can do BFS starting from x in the forward direction, and simultaneously do BFS from y in the reverse direction. 即,您可以从x的正方向进行BFS,同时从y的方向进行BFS。 Ie starting with k=1, you find all vertices you can reach moving forward from x using a path of <= k edges, and you find all vertices you can reach moving reverse-direction from y using <= k edges, and you apply basic BFS principle to increase k by 1. For each k, you hash the vertices you can reach from x, and hash the vertices you can reach from y, and if you get a match w between the two sets then w is a midpoint in a path from x to y, so a path exists. 即从k = 1开始,您发现可以使用<= k条边的路径从x向前移动的所有顶点,并找到您使用<= k边条的从y反向移动的所有顶点,然后应用BFS的基本原理是将k增加1。对于每个k,对可以从x到达的顶点进行哈希处理,对可以从y达到的顶点进行哈希处理,如果在两个集合之间获得匹配w,则w是其中的中点从x到y的路径,因此存在路径。 The reason why this is preferable to BFS starting from x is that if your path from x to y has length K, then BFS starting at x will find all nodes reachable in K steps, which may be a huge set (worst-case exponential in K). 之所以比从x开始的BFS更可取,是因为如果从x到y的路径的长度为K,则从x开始的BFS会发现所有以K步可达的节点,这可能是一个庞大的集合(在K)。 But if you do it the way I proposed, then you can terminate when you reach k >= K/2, and the 2 sets of vertices reachable in K/2 steps will often be much smaller than a set of vertices reachable in K steps. 但是,如果按照我建议的方式进行操作,则可以在达到k> = K / 2时终止,并且以K / 2步可达的2组顶点通常会比以K步可达的一组顶点小得多。 。 So, when a path exists, you will typically find it much faster the way I proposed. 因此,当存在路径时,通常会比我提出的方法快得多。

Approach to this can be. 可以这样处理。

1. BFS (most simple and efficient too)
2. Transitive closure (found using Floyd-Warshall algorithm).

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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