这是LeetCode上的一道题,给定一张图,寻找概率最大的路径。由于这张图是一张正边权图,且目的是找到概率最大的路径,因此我们可以用Dijkstra算法来解决。下面是具体的代码,关键部分都已经给出了注释:
class Solution {
// 迪杰斯特拉算法解决,用BFS+优先级队列实现
public double maxProbability(int n, int[][] edges, double[] succProb, int start, int end) {
List<List<Node>> linkedPath = new ArrayList<List<Node>>();
PriorityQueue<Node> queue = new PriorityQueue<>(new Comparator<Node>(){ // 创建一个优先级队列
public int compare(Node node1, Node node2){
return node2.prob - node1.prob > 0 ? 1 : -1;
}
});
for(int i = 0; i < n; i++){
linkedPath.add(new ArrayList<Node>());
}
for(int i = 0; i < edges.length; i++){ // 用邻接链表存储图
int[] edge = edges[i];
Node node1 = new Node(succProb[i], edge[0]);
Node node2 = new Node(succProb[i], edge[1]);
linkedPath.get(edge[0]).add(node2);
linkedPath.get(edge[1]).add(node1);
}
queue.offer(new Node(1, start));
boolean[] isVisited = new boolean[n];
while(!queue.isEmpty()){ // BFS遍历整张图
Node pre = queue.poll();
if(isVisited[pre.next]) continue;
isVisited[pre.next] = true;
if(pre.next == end) return pre.prob;
for(Node cur : linkedPath.get(pre.next)){
if(isVisited[cur.next]) continue;
queue.offer(new Node(pre.prob * cur.prob, cur.next));
}
}
return 0;
}
class Node{ // 节点数据结构定义
double prob;
int next;
public Node(double prob, int next){
this.prob = prob;
this.next = next;
}
}
}
在这里我们使用了优先级队列和BFS来实现,BFS中最关键的数据结构就是队列,这里我们使用优先级队列来保证到达end时的路径就是概率最大的路径。其中BFS的过程是:将队列头出队,再将与队列头相连的节点入队,一直重复这个操作直到队列为空或者达到end即可完成对这个图的BFS。除此之外,还使用了isVisited数据来标记那些已经访问过的节点,防止往回走,由于这是一个优先级队列,所以当走到end的时候,这条路径就是概率最大的路径。