Katkat

Find the Most Reliable Path Through a Network

NutanixSoftware Engineer · Technical Screen

Last updated

Implement an algorithm to find the maximum end-to-end success probability between two nodes in an undirected network with multiplicative edge probabilities. Tests graph traversal, Dijkstra's algorithm variant with max-heaps, and edge-case handling.

Problem Statement

You are given an undirected graph representing a computer network with n nodes labeled from 0 to n - 1. The network topology is defined by a list of edges, where each edge is specified as [u, v, prob], indicating a bidirectional connection between node u and node v with a transmission success probability of prob (0.0 <= prob <= 1.0).

The reliability (success probability) of a path is defined as the product of the success probabilities of all edges along that path. If a path contains no edges (e.g., from a node to itself), its probability is 1.0.

Write a function max_probability(n: int, edges: list[list[float]], start_node: int, end_node: int) -> float that returns the maximum probability of successfully sending a packet from start_node to end_node. If no path exists between start_node and end_node, return 0.0.

Your solution should properly handle parallel edges (multiple edges between the same pair of nodes), cycles, links with zero probability, and disconnected components.

Function Signature

def max_probability(n: int, edges: list[list[float]], start_node: int, end_node: int) -> float:
    pass

Constraints

  • 1 <= n <= 10^5
  • 0 <= len(edges) <= 2 * 10^5
  • Each edge is a list [u, v, prob] where 0 <= u, v < n and 0.0 <= prob <= 1.0
  • 0 <= start_node, end_node < n
  • Parallel edges and self-loops may be present.
  • Results within 1e-5 of the actual answer will be accepted.

Examples

Example 1

Input: n = 3, edges = [[0, 1, 0.5], [1, 2, 0.5], [0, 2, 0.2]], start_node = 0, end_node = 2
Output: 0.25
Explanation:
Path 0 -> 2 has probability 0.2.
Path 0 -> 1 -> 2 has probability 0.5 * 0.5 = 0.25.
The maximum probability is 0.25.

Example 2

Input: n = 4, edges = [[0, 1, 0.8], [1, 2, 0.5], [2, 3, 0.0]], start_node = 0, end_node = 3
Output: 0.0
Explanation:
Any path reaching node 3 must pass through the edge with probability 0.0, resulting in a total path probability of 0.0.

Example 3

Input: n = 3, edges = [[0, 1, 0.4]], start_node = 0, end_node = 2
Output: 0.0
Explanation: Node 2 is not reachable from node 0.

Hints

Hint 1

Since edge probabilities are in [0, 1], multiplying by an edge probability never increases the total probability, mirroring the non-decreasing property in Dijkstra's shortest path algorithm.

Hint 2

Use a max-heap (or a min-heap with negated values) to greedily expand the vertex with the current highest accumulated probability.

Hint 3

Take care when start_node == end_node: what should the base probability be, and can it ever be less than 1.0?

Follow-up questions

  • How would you modify your approach if edge probabilities were extremely small (e.g., 10^-100) such that floating-point underflow becomes an issue?
  • How can you reconstruct and return the actual path of nodes yielding the maximum probability instead of just the value?
  • If edge weights could be greater than 1.0 (amplification rather than attenuation), why would this greedy approach fail, and what algorithm could be used instead?