Given an undirected tree consisting of n vertices numbered from 1 to n. A frog starts jumping from the 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] = [fromi, toi] means that exists an edge connecting directly the vertices fromi and toi.
Return the probability that after t seconds the frog is on the vertex target.
Example 1:

Input: n = 7, edges = [[1,2],[1,3],[1,7],[2,4],[2,6],[3,5]], t = 2, target = 4Output: 0.16666666666666666Explanation: The figure above shows the given graph. The frog starts at vertex 1, jumping with 1/3 probability to the vertex 2 after second 1 and then jumping with 1/2 probability to vertex 4 after second 2. Thus the probability for the frog is on the vertex 4 after 2 seconds is 1/3 * 1/2 = 1/6 = 0.16666666666666666.
Example 2:

Input: n = 7, edges = [[1,2],[1,3],[1,7],[2,4],[2,6],[3,5]], t = 1, target = 7Output: 0.3333333333333333Explanation: The figure above shows the given graph. The frog starts at vertex 1, jumping with 1/3 = 0.3333333333333333 probability to the vertex 7 after second 1.
Example 3:
Input: n = 7, edges = [[1,2],[1,3],[1,7],[2,4],[2,6],[3,5]], t = 20, target = 6Output: 0.16666666666666666
Constraints:
1 <= n <= 100edges.length == n-1edges[i].length == 21 <= edges[i][0], edges[i][1] <= n1 <= t <= 501 <= target <= n- Answers within
10^-5of the actual value will be accepted as correct.
题意
给定一个无向图,一个🐸从结点1开始跳,必须跳t下,每一次跳向邻近点的概率都是相同的,且不能往回跳,无路可跳时则原地跳,问该🐸最后停在指定的结点处的概率。
思路
首先要注意这实际上是一张图而不是以1为根结点的树。
两种方法:
- 利用BFS从结点1开始向外走t层,记录下到达每个结点的概率;
- 也可以利用DFS找到目标节点,在寻找过程中生成路径(即 到达点->出发点),最后统计从结点1走到目标结点的概率。
代码实现 - BFS
class Solution {public double frogPosition(int n, int[][] edges, int t, int target) {// 生成图List<List<Integer>> graph = new ArrayList<>();for (int i = 0; i <= n; i++) {graph.add(new ArrayList<>());}for (int[] edge : edges) {graph.get(edge[0]).add(edge[1]);graph.get(edge[1]).add(edge[0]);}// BFS处理boolean[] visited = new boolean[n + 1];Queue<Integer> q = new LinkedList<>();double[] prob = new double[n + 1];q.offer(1);visited[1] = true;prob[1] = 1;while (!q.isEmpty() && t-- > 0) {int size = q.size();for (int i = 0; i < size; i++) {int u = q.poll();int neighbors = 0;for (int v : graph.get(u)) {if (!visited[v]) {neighbors++;}}for (int v : graph.get(u)) {if (!visited[v]) {visited[v] = true;q.offer(v);prob[v] = prob[u] / neighbors;}}// 还需继续跳且存在可以跳的结点时,一定不会停留在当前结点if (neighbors != 0) {prob[u] = 0;}}}return prob[target];}}
代码实现 - DFS
class Solution {public double frogPosition(int n, int[][] edges, int t, int target) {// 生成图List<List<Integer>> graph = new ArrayList<>();for (int i = 0; i <= n; i++) {graph.add(new ArrayList<>());}for (int[] edge : edges) {graph.get(edge[0]).add(edge[1]);graph.get(edge[1]).add(edge[0]);}// dfs处理int[] prev = new int[n + 1];boolean[] visited = new boolean[n + 1];visited[1] = true;int len = dfs(1, target, graph, prev, visited);// 存在以下情况可以判断无法停在target:// 1. 跳跃的次数小于1到target的长度// 2. 跳跃次数大于1到target的长度且还存在可以跳的结点if (t < len || t > len && (target == 1 && graph.get(1).size() > 0 || graph.get(target).size() > 1)) {return 0;}// 累乘得到从结点1走到target的概率的分母int denominator = 1;while (prev[target] != 0) {target = prev[target];denominator *= target == 1 ? graph.get(1).size() : graph.get(target).size() - 1;}return 1.0 / denominator;}// 返回从u到target的长度,无法到达则返回-1private int dfs(int u, int target, List<List<Integer>> graph, int[] prev, boolean[] visited) {if (u == target) {return 0;}for (int v : graph.get(u)) {if (!visited[v]) {visited[v] = true;prev[v] = u;int len = dfs(v, target, graph, prev, visited);if (len >= 0) {return 1 + len;}}}return -1;}}
