Problem: Frog Position After T Seconds

Given an undirected tree consisting of `n` vertices numbered from `1` to `n`.
A frog starts jumping from vertex 1. In one second, the frog jumps from its
current vertex to another unvisited vertex if they are directly connected. The
frog can not jump back to a visited vertex. In case the frog can jump to
several vertices, it jumps randomly to one of them with the same probability.
Otherwise, when the frog can not jump to any unvisited vertex, it jumps
forever on the same vertex.

The edges of the undirected tree are given in the array `edges`, where
`edges[i] = [ai, bi]` means that exists an edge connecting the vertices `ai`
and `bi`.

Return the probability that after `t` seconds the frog is on the vertex
`target`. Answers within `10-5` of the actual answer will be accepted.


Python solution:
import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def frogPosition(self, n: int, edges: List[List[int]], t: int, target: int) -> float:
    tree = [[] for _ in range(n + 1)]
    q = collections.deque([1])
    seen = [False] * (n + 1)
    prob = [0] * (n + 1)

    prob[1] = 1
    seen[1] = True

    for u, v in edges:
      tree[u].append(v)
      tree[v].append(u)

    for _ in range(t):
      for _ in range(len(q)):
        a = q.popleft()
        nChildren = sum(not seen[b] for b in tree[a])
        for b in tree[a]:
          if seen[b]:
            continue
          seen[b] = True
          prob[b] = prob[a] / nChildren
          q.append(b)
        if nChildren > 0:
          prob[a] = 0

    return prob[target]


Java solution:
class Solution {
  public double frogPosition(int n, int[][] edges, int t, int target) {
    List<Integer>[] tree = new List[n + 1];
    Queue<Integer> q = new ArrayDeque<>(List.of(1));
    boolean[] seen = new boolean[n + 1];
    double[] prob = new double[n + 1];

    seen[1] = true;
    prob[1] = 1.0;

    for (int i = 1; i <= n; ++i)
      tree[i] = new ArrayList<>();

    for (int[] edge : edges) {
      final int u = edge[0];
      final int v = edge[1];
      tree[u].add(v);
      tree[v].add(u);
    }

    while (!q.isEmpty() && t-- > 0)
      for (int sz = q.size(); sz > 0; --sz) {
        final int a = q.poll();
        int nChildren = 0;
        for (final int b : tree[a])
          if (!seen[b])
            ++nChildren;
        for (final int b : tree[a]) {
          if (seen[b])
            continue;
          seen[b] = true;
          prob[b] = prob[a] / nChildren;
          q.add(b);
        }
        if (nChildren > 0)
          prob[a] = 0.0;
      }

    return prob[target];
  }
}


C++ solution:
class Solution {
 public:
  double frogPosition(int n, vector<vector<int>>& edges, int t, int target) {
    vector<vector<int>> tree(n + 1);
    queue<int> q{{1}};
    vector<bool> seen(n + 1);
    vector<double> prob(n + 1);

    seen[1] = true;
    prob[1] = 1.0;

    for (const vector<int>& edge : edges) {
      const int u = edge[0];
      const int v = edge[1];
      tree[u].push_back(v);
      tree[v].push_back(u);
    }

    while (!q.empty() && t-- > 0)
      for (int sz = q.size(); sz > 0; --sz) {
        const int a = q.front();
        q.pop();
        const int nChildren =
            ranges::count_if(tree[a], [&seen](int b) { return !seen[b]; });
        for (const int b : tree[a]) {
          if (seen[b])
            continue;
          seen[b] = true;
          prob[b] = prob[a] / nChildren;
          q.push(b);
        }
        if (nChildren > 0)
          prob[a] = 0.0;
      }

    return prob[target];
  }
};