Path with Maximum Probability

MediumGraphs · Dijkstra (Max-Heap)🧩 Shortest PathsLeetCode #1514 ↗Updated

Problem

An undirected graph has n nodes. Edge edges[i] = [a, b] can be crossed successfully with probability succProb[i]. A path succeeds only if every edge on it succeeds, so its probability is the product of its edge probabilities. Return the highest success probability of any path from start_node to end_node, or 0 if they are not connected (answers within 1e-5 are accepted).
Inputn=3, edges=[[0,1],[1,2],[0,2]], succProb=[0.5,0.5,0.2], start=0, end=2Output0.25
Inputn=3, edges=[[0,1],[1,2],[0,2]], succProb=[0.5,0.5,0.3], start=0, end=2Output0.3
Inputn=3, edges=[[0,1]], succProb=[0.5], start=0, end=2Output0.0

2 ≤ n ≤ 104  ·  0 ≤ edges.length ≤ 2·104  ·  0 ≤ succProb[i] ≤ 1  ·  at most one edge per pair  ·  start ≠ end

Try it yourself

Java
class Solution {
    public double maxProbability(int n, int[][] edges, double[] succProb, int start_node, int end_node) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Multiplying by a probability in [0, 1] can never increase the value — the mirror image of adding a non-negative weight. So Dijkstra works unchanged if you use a max-heap and “relax” with multiplication.
PatternShortest Paths

Instinct Weighted edges plus "minimum cost, time or effort to reach" - grab a min-heap and always expand the cheapest unsettled node next (Dijkstra).

Memory hack Pop the cheapest, skip the stale, relax the rest - Dijkstra is a ripple in a pond that touches near shores before far ones.

Open the Shortest Paths guide →

Approaches

Brute ForceBellman-Ford Relaxation

Time O(V · E)Space O(V)

Set best[start] = 1. In each round, relax every edge in both directions: best[v] = max(best[v], best[u] × p). A best path uses at most V-1 edges, so V-1 rounds suffice; stop early once a round changes nothing.

Java
public double maxProbability(int n, int[][] edges, double[] succProb,
                            int start_node, int end_node) {
    double[] best = new double[n];
    best[start_node] = 1.0;
    for (int round = 0; round < n - 1; round++) {
        boolean changed = false;
        for (int i = 0; i < edges.length; i++) {
            int a = edges[i][0], b = edges[i][1];
            double p = succProb[i];
            if (best[a] * p > best[b]) { best[b] = best[a] * p; changed = true; }
            if (best[b] * p > best[a]) { best[a] = best[b] * p; changed = true; }
        }
        if (!changed) break; // nothing improved: values are final
    }
    return best[end_node];
}

Simple and needs no adjacency list, but can sweep all edges V times.

At a glance

LevelApproachTimeSpace
Brute ForceBellman-Ford RelaxationO(V · E)O(V)
BetterQueue-Based Relaxation (SPFA)O(V · E) worst, much less on averageO(V + E)
OptimalDijkstra with a Max-HeapO((V + E) log V)O(V + E)
Common pitfalls
  • Using a min-heap out of habit — you want the largest probability first.
  • Adding edges in only one direction — the graph is undirected.
  • Comparing doubles with == in tests — use a small tolerance.
Interview tips
  • Justify Dijkstra: multiplying by p ≤ 1 is monotone, like adding a weight ≥ 0.
  • Mention the −log transform to connect it to standard shortest paths.
  • Point out the early return when the target is popped.
Pattern
Dijkstra variant → best path where extending a path can only make it worse (sum ≥ 0, product ≤ 1, max).
My notes saved in this browser