[英]Given a directed graph, find out whether there is a route between two nodes
我正在嘗試解決這個問題,我對圖形還很陌生。 我試圖通過BFS來解決這個問題,但是我沒有得到正確的答案。
我究竟做錯了什么? 另外,除了我使用的方法之外,還有沒有更好的方法可以做到這一點。
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;
}
對於檢查-
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)));
我會說BFS是在這里應用的正確算法,因此這只是您的BFS代碼的問題。 您似乎對圖在鄰接矩陣中的表示方式感到困惑。
if((top.x1 == n2.x1) && (top.y1 == n2.y1)){
// found our node;
return true;
}
這是在檢查是否已到達鄰接矩陣(邊)中的特定條目,但是您只是要檢查給定節點是否可到達。
您應該更改gNode
表示形式以使用單個索引(或者只是刪除它並使用int
代替),並根據鄰接矩陣值從第一個節點開始執行BFS。
如果您在了解算法/數據結構方面需要其他幫助,則此頁面似乎是不錯的參考: 鄰接矩陣,BFS,DFS 。
如果我不太熟悉該語言,則我不擅長調試10-20行以上的代碼。 但是,我可以告訴您,有一種更好的整體方法來判斷兩個節點x和y之間是否存在路徑,而不是僅僅從x開始的BFS或DFS。 即,您可以從x的正方向進行BFS,同時從y的方向進行BFS。 即從k = 1開始,您發現可以使用<= k條邊的路徑從x向前移動的所有頂點,並找到您使用<= k邊條的從y反向移動的所有頂點,然后應用BFS的基本原理是將k增加1。對於每個k,對可以從x到達的頂點進行哈希處理,對可以從y達到的頂點進行哈希處理,如果在兩個集合之間獲得匹配w,則w是其中的中點從x到y的路徑,因此存在路徑。 之所以比從x開始的BFS更可取,是因為如果從x到y的路徑的長度為K,則從x開始的BFS會發現所有以K步可達的節點,這可能是一個龐大的集合(在K)。 但是,如果按照我建議的方式進行操作,則可以在達到k> = K / 2時終止,並且以K / 2步可達的2組頂點通常會比以K步可達的一組頂點小得多。 。 因此,當存在路徑時,通常會比我提出的方法快得多。
可以這樣處理。
1. BFS (most simple and efficient too)
2. Transitive closure (found using Floyd-Warshall algorithm).
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.