Given a binary tree `root` and an integer `target`, delete all the **leaf nodes** with value `target`.

Note that once you delete a leaf node with value `target`**,** if its parent node becomes a leaf node and has the value `target`, it should also be deleted (you need to continue doing that until you cannot).

**Example 1:**

**Input:** root = \[1,2,3,2,null,2,4\], target = 2
**Output:** \[1,null,3,null,4\]
**Explanation:** Leaf nodes in green with value (target = 2) are removed (Picture in left). 
After removing, new nodes become leaf nodes with value (target = 2) (Picture in center).

**Example 2:**

**Input:** root = \[1,3,3,3,2\], target = 3
**Output:** \[1,3,null,null,2\]

**Example 3:**

**Input:** root = \[1,2,null,2,null,2\], target = 2
**Output:** \[1\]
**Explanation:** Leaf nodes in green with value (target = 2) are removed at each step.

**Constraints:**

*   The number of nodes in the tree is in the range `[1, 3000]`.
*   `1 <= Node.val, target <= 1000`


from heapq import heappush, heappop


def maxProbability(n, edges, succProb, start, end):
    graph = [[] for _ in range(n)]
    for i in range(len(edges)):
        a, b = edges[i]
        graph[a].append((b, succProb[i]))
        graph[b].append((a, succProb[i]))

    max_prob = [0] * n
    max_prob[start] = 1

    pq = [(-1, start)]

    while pq:
        prob, node = heappop(pq)

        if node == end:
            return -prob

        if -prob < max_prob[node]:
            continue

        for neighbor, edge_prob in graph[node]:
            new_prob = -prob * edge_prob
            if new_prob > max_prob[neighbor]:
                max_prob[neighbor] = new_prob
                heappush(pq, (-new_prob, neighbor))

    return 0
