[英]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.