diff --git a/solution/1500-1599/1514.Path with Maximum Probability/README.md b/solution/1500-1599/1514.Path with Maximum Probability/README.md index 88b08e481fe02..df571cee461de 100644 --- a/solution/1500-1599/1514.Path with Maximum Probability/README.md +++ b/solution/1500-1599/1514.Path with Maximum Probability/README.md @@ -78,7 +78,15 @@ tags: ### 方法一:堆优化 Dijkstra 算法 -时间复杂度 O(mlogn)。 +我们可以使用 Dijkstra 算法求解最短路径,这里我们稍微修改一下,求解最大概率路径。 + +我们可以使用一个优先队列(大根堆) $\textit{pq}$ 来存储从起点到各个节点的概率以及节点编号。初始时我们将起点的概率设为 $1$,其余节点的概率设为 $0$,然后将起点加入到 $\textit{pq}$ 中。 + +在每一次的迭代中,我们取出 $\textit{pq}$ 中概率最大的节点 $a$,以及 $a$ 的概率 $w$。如果节点 $a$ 的概率已经大于 $w$,那么我们就可以跳过这个节点。否则我们遍历 $a$ 的所有邻接边 $(a, b)$。如果 $b$ 的概率小于 $a$ 的概率乘以 $(a, b)$ 的概率,那么我们就可以更新 $b$ 的概率,并将 $b$ 加入到 $\textit{pq}$ 中。 + +最终,我们可以得到从起点到终点的最大概率。 + +时间复杂度 $O(m \times \log m)$,空间复杂度 $O(m)$。其中 $m$ 为边的数量。 @@ -91,61 +99,66 @@ class Solution: n: int, edges: List[List[int]], succProb: List[float], - start: int, - end: int, + start_node: int, + end_node: int, ) -> float: - g = defaultdict(list) - for (a, b), s in zip(edges, succProb): - g[a].append((b, s)) - g[b].append((a, s)) - q = [(-1, start)] - d = [0] * n - d[start] = 1 - while q: - w, u = heappop(q) + g: List[List[Tuple[int, float]]] = [[] for _ in range(n)] + for (a, b), p in zip(edges, succProb): + g[a].append((b, p)) + g[b].append((a, p)) + pq = [(-1, start_node)] + dist = [0] * n + dist[start_node] = 1 + while pq: + w, a = heappop(pq) w = -w - if d[u] > w: + if dist[a] > w: continue - for v, t in g[u]: - if d[v] < d[u] * t: - d[v] = d[u] * t - heappush(q, (-d[v], v)) - return d[end] + for b, p in g[a]: + if (t := w * p) > dist[b]: + dist[b] = t + heappush(pq, (-t, b)) + return dist[end_node] ``` #### Java ```java class Solution { - public double maxProbability(int n, int[][] edges, double[] succProb, int start, int end) { + public double maxProbability( + int n, int[][] edges, double[] succProb, int start_node, int end_node) { List>[] g = new List[n]; Arrays.setAll(g, k -> new ArrayList<>()); for (int i = 0; i < edges.length; ++i) { - int a = edges[i][0], b = edges[i][1]; - double s = succProb[i]; - g[a].add(new Pair<>(b, s)); - g[b].add(new Pair<>(a, s)); + var e = edges[i]; + int a = e[0], b = e[1]; + double p = succProb[i]; + g[a].add(new Pair<>(b, p)); + g[b].add(new Pair<>(a, p)); } - PriorityQueue> q - = new PriorityQueue<>(Comparator.comparingDouble(Pair::getKey)); - double[] d = new double[n]; - d[start] = 1.0; - q.offer(new Pair<>(-1.0, start)); - while (!q.isEmpty()) { - Pair p = q.poll(); - double w = p.getKey(); - w *= -1; - int u = p.getValue(); - for (Pair ne : g[u]) { - int v = ne.getKey(); - double t = ne.getValue(); - if (d[v] < d[u] * t) { - d[v] = d[u] * t; - q.offer(new Pair<>(-d[v], v)); + double[] dist = new double[n]; + dist[start_node] = 1; + PriorityQueue> pq + = new PriorityQueue<>(Comparator.comparingDouble(p -> - p.getValue())); + pq.offer(new Pair<>(start_node, 1.0)); + while (!pq.isEmpty()) { + var p = pq.poll(); + int a = p.getKey(); + double w = p.getValue(); + if (dist[a] > w) { + continue; + } + for (var e : g[a]) { + int b = e.getKey(); + double pab = e.getValue(); + double wab = w * pab; + if (wab > dist[b]) { + dist[b] = wab; + pq.offer(new Pair<>(b, wab)); } } } - return d[end]; + return dist[end_node]; } } ``` @@ -155,34 +168,34 @@ class Solution { ```cpp class Solution { public: - double maxProbability(int n, vector>& edges, vector& succProb, int start, int end) { - vector>> g(n); + double maxProbability(int n, vector>& edges, vector& succProb, int start_node, int end_node) { + using pdi = pair; + vector g[n]; for (int i = 0; i < edges.size(); ++i) { int a = edges[i][0], b = edges[i][1]; - double s = succProb[i]; - g[a].push_back({b, s}); - g[b].push_back({a, s}); + double p = succProb[i]; + g[a].emplace_back(p, b); + g[b].emplace_back(p, a); } - vector d(n); - d[start] = 1.0; - queue> q; - q.push({1.0, start}); - while (!q.empty()) { - auto p = q.front(); - q.pop(); - double w = p.first; - int u = p.second; - if (d[u] > w) continue; - for (auto& e : g[u]) { - int v = e.first; - double t = e.second; - if (d[v] < d[u] * t) { - d[v] = d[u] * t; - q.push({d[v], v}); + vector dist(n); + dist[start_node] = 1; + priority_queue pq; + pq.emplace(1, start_node); + while (!pq.empty()) { + auto [w, a] = pq.top(); + pq.pop(); + if (dist[a] > w) { + continue; + } + for (auto [p, b] : g[a]) { + auto nw = w * p; + if (nw > dist[b]) { + dist[b] = nw; + pq.emplace(nw, b); } } } - return d[end]; + return dist[end_node]; } }; ``` @@ -190,163 +203,82 @@ public: #### Go ```go -func maxProbability(n int, edges [][]int, succProb []float64, start int, end int) float64 { +func maxProbability(n int, edges [][]int, succProb []float64, start_node int, end_node int) float64 { g := make([][]pair, n) for i, e := range edges { - a, b, s := e[0], e[1], succProb[i] - g[a] = append(g[a], pair{b, s}) - g[b] = append(g[b], pair{a, s}) + a, b := e[0], e[1] + p := succProb[i] + g[a] = append(g[a], pair{p, b}) + g[b] = append(g[b], pair{p, a}) } - d := make([]float64, n) - d[start] = 1 - vis := make([]bool, n) - q := []int{start} - vis[start] = true - for len(q) > 0 { - i := q[0] - q = q[1:] - vis[i] = false - for _, ne := range g[i] { - j, s := ne.idx, ne.s - if d[j] < d[i]*s { - d[j] = d[i] * s - if !vis[j] { - q = append(q, j) - vis[j] = true - } + pq := hp{{1, start_node}} + dist := make([]float64, n) + dist[start_node] = 1 + for len(pq) > 0 { + p := heap.Pop(&pq).(pair) + w, a := p.p, p.a + if dist[a] > w { + continue + } + for _, e := range g[a] { + b, p := e.a, e.p + if nw := w * p; nw > dist[b] { + dist[b] = nw + heap.Push(&pq, pair{nw, b}) } } } - return d[end] + return dist[end_node] } type pair struct { - idx int - s float64 + p float64 + a int } -``` - - +type hp []pair - - - - -### 方法二:SPFA 算法 - -时间复杂度,平均情况下 O(m),最坏情况下 O(nm),n 表示点数,m 表示边数。 - - - -#### Python3 - -```python -class Solution: - def maxProbability( - self, - n: int, - edges: List[List[int]], - succProb: List[float], - start: int, - end: int, - ) -> float: - g = defaultdict(list) - for (a, b), s in zip(edges, succProb): - g[a].append((b, s)) - g[b].append((a, s)) - d = [0] * n - vis = [False] * n - d[start] = 1 - q = deque([start]) - vis[start] = True - while q: - i = q.popleft() - vis[i] = False - for j, s in g[i]: - if d[j] < d[i] * s: - d[j] = d[i] * s - if not vis[j]: - q.append(j) - vis[j] = True - return d[end] +func (h hp) Len() int { return len(h) } +func (h hp) Less(i, j int) bool { return h[i].p > h[j].p } +func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *hp) Push(x any) { *h = append(*h, x.(pair)) } +func (h *hp) Pop() (x any) { a := *h; x = a[len(a)-1]; *h = a[:len(a)-1]; return } ``` -#### Java - -```java -class Solution { - public double maxProbability(int n, int[][] edges, double[] succProb, int start, int end) { - List>[] g = new List[n]; - Arrays.setAll(g, k -> new ArrayList<>()); - for (int i = 0; i < edges.length; ++i) { - int a = edges[i][0], b = edges[i][1]; - double s = succProb[i]; - g[a].add(new Pair<>(b, s)); - g[b].add(new Pair<>(a, s)); - } - double[] d = new double[n]; - d[start] = 1.0; - boolean[] vis = new boolean[n]; - Deque q = new ArrayDeque<>(); - q.offer(start); - vis[start] = true; - while (!q.isEmpty()) { - int i = q.poll(); - vis[i] = false; - for (Pair ne : g[i]) { - int j = ne.getKey(); - double s = ne.getValue(); - if (d[j] < d[i] * s) { - d[j] = d[i] * s; - if (!vis[j]) { - q.offer(j); - vis[j] = true; - } - } - } - } - return d[end]; +#### TypeScript + +```ts +function maxProbability( + n: number, + edges: number[][], + succProb: number[], + start_node: number, + end_node: number, +): number { + const pq = new MaxPriorityQueue({ priority: v => v[0] }); + const g: [number, number][][] = Array.from({ length: n }, () => []); + for (let i = 0; i < edges.length; ++i) { + const [a, b] = edges[i]; + g[a].push([b, succProb[i]]); + g[b].push([a, succProb[i]]); } -} -``` - -#### C++ - -```cpp -class Solution { -public: - double maxProbability(int n, vector>& edges, vector& succProb, int start, int end) { - vector>> g(n); - for (int i = 0; i < edges.size(); ++i) { - int a = edges[i][0], b = edges[i][1]; - double s = succProb[i]; - g[a].push_back({b, s}); - g[b].push_back({a, s}); + const dist = Array.from({ length: n }, () => 0); + dist[start_node] = 1; + pq.enqueue([1, start_node]); + while (!pq.isEmpty()) { + const [w, a] = pq.dequeue().element; + if (dist[a] > w) { + continue; } - vector d(n); - vector vis(n); - d[start] = 1.0; - queue q{{start}}; - vis[start] = true; - while (!q.empty()) { - int i = q.front(); - q.pop(); - vis[i] = false; - for (auto& ne : g[i]) { - int j = ne.first; - double s = ne.second; - if (d[j] < d[i] * s) { - d[j] = d[i] * s; - if (!vis[j]) { - q.push(j); - vis[j] = true; - } - } + for (const [b, p] of g[a]) { + const nw = w * p; + if (nw > dist[b]) { + dist[b] = nw; + pq.enqueue([nw, b]); } } - return d[end]; } -}; + return dist[end_node]; +} ``` diff --git a/solution/1500-1599/1514.Path with Maximum Probability/README_EN.md b/solution/1500-1599/1514.Path with Maximum Probability/README_EN.md index a575f1aa4cb56..f736ca5fba99d 100644 --- a/solution/1500-1599/1514.Path with Maximum Probability/README_EN.md +++ b/solution/1500-1599/1514.Path with Maximum Probability/README_EN.md @@ -77,7 +77,17 @@ tags: -### Solution 1 +### Solution 1: Heap-Optimized Dijkstra Algorithm + +We can use Dijkstra's algorithm to find the shortest path, but here we modify it slightly to find the path with the maximum probability. + +We use a priority queue (max-heap) $\textit{pq}$ to store the probability from the starting point to each node and the node's identifier. Initially, we set the probability of the starting point to $1$ and the probabilities of the other nodes to $0$, then add the starting point to $\textit{pq}$. + +In each iteration, we take out the node $a$ with the highest probability from $\textit{pq}$ and its probability $w$. If the probability of node $a$ is already greater than $w$, we can skip this node. Otherwise, we traverse all adjacent edges $(a, b)$ of $a$. If the probability of $b$ is less than the probability of $a$ multiplied by the probability of $(a, b)$, we update the probability of $b$ and add $b$ to $\textit{pq}$. + +Finally, we obtain the maximum probability from the starting point to the endpoint. + +The time complexity is $O(m \times \log m)$, and the space complexity is $O(m)$. Here, $m$ is the number of edges. @@ -90,61 +100,66 @@ class Solution: n: int, edges: List[List[int]], succProb: List[float], - start: int, - end: int, + start_node: int, + end_node: int, ) -> float: - g = defaultdict(list) - for (a, b), s in zip(edges, succProb): - g[a].append((b, s)) - g[b].append((a, s)) - q = [(-1, start)] - d = [0] * n - d[start] = 1 - while q: - w, u = heappop(q) + g: List[List[Tuple[int, float]]] = [[] for _ in range(n)] + for (a, b), p in zip(edges, succProb): + g[a].append((b, p)) + g[b].append((a, p)) + pq = [(-1, start_node)] + dist = [0] * n + dist[start_node] = 1 + while pq: + w, a = heappop(pq) w = -w - if d[u] > w: + if dist[a] > w: continue - for v, t in g[u]: - if d[v] < d[u] * t: - d[v] = d[u] * t - heappush(q, (-d[v], v)) - return d[end] + for b, p in g[a]: + if (t := w * p) > dist[b]: + dist[b] = t + heappush(pq, (-t, b)) + return dist[end_node] ``` #### Java ```java class Solution { - public double maxProbability(int n, int[][] edges, double[] succProb, int start, int end) { + public double maxProbability( + int n, int[][] edges, double[] succProb, int start_node, int end_node) { List>[] g = new List[n]; Arrays.setAll(g, k -> new ArrayList<>()); for (int i = 0; i < edges.length; ++i) { - int a = edges[i][0], b = edges[i][1]; - double s = succProb[i]; - g[a].add(new Pair<>(b, s)); - g[b].add(new Pair<>(a, s)); + var e = edges[i]; + int a = e[0], b = e[1]; + double p = succProb[i]; + g[a].add(new Pair<>(b, p)); + g[b].add(new Pair<>(a, p)); } - PriorityQueue> q - = new PriorityQueue<>(Comparator.comparingDouble(Pair::getKey)); - double[] d = new double[n]; - d[start] = 1.0; - q.offer(new Pair<>(-1.0, start)); - while (!q.isEmpty()) { - Pair p = q.poll(); - double w = p.getKey(); - w *= -1; - int u = p.getValue(); - for (Pair ne : g[u]) { - int v = ne.getKey(); - double t = ne.getValue(); - if (d[v] < d[u] * t) { - d[v] = d[u] * t; - q.offer(new Pair<>(-d[v], v)); + double[] dist = new double[n]; + dist[start_node] = 1; + PriorityQueue> pq + = new PriorityQueue<>(Comparator.comparingDouble(p -> - p.getValue())); + pq.offer(new Pair<>(start_node, 1.0)); + while (!pq.isEmpty()) { + var p = pq.poll(); + int a = p.getKey(); + double w = p.getValue(); + if (dist[a] > w) { + continue; + } + for (var e : g[a]) { + int b = e.getKey(); + double pab = e.getValue(); + double wab = w * pab; + if (wab > dist[b]) { + dist[b] = wab; + pq.offer(new Pair<>(b, wab)); } } } - return d[end]; + return dist[end_node]; } } ``` @@ -154,34 +169,34 @@ class Solution { ```cpp class Solution { public: - double maxProbability(int n, vector>& edges, vector& succProb, int start, int end) { - vector>> g(n); + double maxProbability(int n, vector>& edges, vector& succProb, int start_node, int end_node) { + using pdi = pair; + vector g[n]; for (int i = 0; i < edges.size(); ++i) { int a = edges[i][0], b = edges[i][1]; - double s = succProb[i]; - g[a].push_back({b, s}); - g[b].push_back({a, s}); + double p = succProb[i]; + g[a].emplace_back(p, b); + g[b].emplace_back(p, a); } - vector d(n); - d[start] = 1.0; - queue> q; - q.push({1.0, start}); - while (!q.empty()) { - auto p = q.front(); - q.pop(); - double w = p.first; - int u = p.second; - if (d[u] > w) continue; - for (auto& e : g[u]) { - int v = e.first; - double t = e.second; - if (d[v] < d[u] * t) { - d[v] = d[u] * t; - q.push({d[v], v}); + vector dist(n); + dist[start_node] = 1; + priority_queue pq; + pq.emplace(1, start_node); + while (!pq.empty()) { + auto [w, a] = pq.top(); + pq.pop(); + if (dist[a] > w) { + continue; + } + for (auto [p, b] : g[a]) { + auto nw = w * p; + if (nw > dist[b]) { + dist[b] = nw; + pq.emplace(nw, b); } } } - return d[end]; + return dist[end_node]; } }; ``` @@ -189,161 +204,82 @@ public: #### Go ```go -func maxProbability(n int, edges [][]int, succProb []float64, start int, end int) float64 { +func maxProbability(n int, edges [][]int, succProb []float64, start_node int, end_node int) float64 { g := make([][]pair, n) for i, e := range edges { - a, b, s := e[0], e[1], succProb[i] - g[a] = append(g[a], pair{b, s}) - g[b] = append(g[b], pair{a, s}) + a, b := e[0], e[1] + p := succProb[i] + g[a] = append(g[a], pair{p, b}) + g[b] = append(g[b], pair{p, a}) } - d := make([]float64, n) - d[start] = 1 - vis := make([]bool, n) - q := []int{start} - vis[start] = true - for len(q) > 0 { - i := q[0] - q = q[1:] - vis[i] = false - for _, ne := range g[i] { - j, s := ne.idx, ne.s - if d[j] < d[i]*s { - d[j] = d[i] * s - if !vis[j] { - q = append(q, j) - vis[j] = true - } + pq := hp{{1, start_node}} + dist := make([]float64, n) + dist[start_node] = 1 + for len(pq) > 0 { + p := heap.Pop(&pq).(pair) + w, a := p.p, p.a + if dist[a] > w { + continue + } + for _, e := range g[a] { + b, p := e.a, e.p + if nw := w * p; nw > dist[b] { + dist[b] = nw + heap.Push(&pq, pair{nw, b}) } } } - return d[end] + return dist[end_node] } type pair struct { - idx int - s float64 + p float64 + a int } -``` - - - - +type hp []pair - - -### Solution 2 - - - -#### Python3 - -```python -class Solution: - def maxProbability( - self, - n: int, - edges: List[List[int]], - succProb: List[float], - start: int, - end: int, - ) -> float: - g = defaultdict(list) - for (a, b), s in zip(edges, succProb): - g[a].append((b, s)) - g[b].append((a, s)) - d = [0] * n - vis = [False] * n - d[start] = 1 - q = deque([start]) - vis[start] = True - while q: - i = q.popleft() - vis[i] = False - for j, s in g[i]: - if d[j] < d[i] * s: - d[j] = d[i] * s - if not vis[j]: - q.append(j) - vis[j] = True - return d[end] +func (h hp) Len() int { return len(h) } +func (h hp) Less(i, j int) bool { return h[i].p > h[j].p } +func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *hp) Push(x any) { *h = append(*h, x.(pair)) } +func (h *hp) Pop() (x any) { a := *h; x = a[len(a)-1]; *h = a[:len(a)-1]; return } ``` -#### Java - -```java -class Solution { - public double maxProbability(int n, int[][] edges, double[] succProb, int start, int end) { - List>[] g = new List[n]; - Arrays.setAll(g, k -> new ArrayList<>()); - for (int i = 0; i < edges.length; ++i) { - int a = edges[i][0], b = edges[i][1]; - double s = succProb[i]; - g[a].add(new Pair<>(b, s)); - g[b].add(new Pair<>(a, s)); - } - double[] d = new double[n]; - d[start] = 1.0; - boolean[] vis = new boolean[n]; - Deque q = new ArrayDeque<>(); - q.offer(start); - vis[start] = true; - while (!q.isEmpty()) { - int i = q.poll(); - vis[i] = false; - for (Pair ne : g[i]) { - int j = ne.getKey(); - double s = ne.getValue(); - if (d[j] < d[i] * s) { - d[j] = d[i] * s; - if (!vis[j]) { - q.offer(j); - vis[j] = true; - } - } - } - } - return d[end]; +#### TypeScript + +```ts +function maxProbability( + n: number, + edges: number[][], + succProb: number[], + start_node: number, + end_node: number, +): number { + const pq = new MaxPriorityQueue({ priority: v => v[0] }); + const g: [number, number][][] = Array.from({ length: n }, () => []); + for (let i = 0; i < edges.length; ++i) { + const [a, b] = edges[i]; + g[a].push([b, succProb[i]]); + g[b].push([a, succProb[i]]); } -} -``` - -#### C++ - -```cpp -class Solution { -public: - double maxProbability(int n, vector>& edges, vector& succProb, int start, int end) { - vector>> g(n); - for (int i = 0; i < edges.size(); ++i) { - int a = edges[i][0], b = edges[i][1]; - double s = succProb[i]; - g[a].push_back({b, s}); - g[b].push_back({a, s}); + const dist = Array.from({ length: n }, () => 0); + dist[start_node] = 1; + pq.enqueue([1, start_node]); + while (!pq.isEmpty()) { + const [w, a] = pq.dequeue().element; + if (dist[a] > w) { + continue; } - vector d(n); - vector vis(n); - d[start] = 1.0; - queue q{{start}}; - vis[start] = true; - while (!q.empty()) { - int i = q.front(); - q.pop(); - vis[i] = false; - for (auto& ne : g[i]) { - int j = ne.first; - double s = ne.second; - if (d[j] < d[i] * s) { - d[j] = d[i] * s; - if (!vis[j]) { - q.push(j); - vis[j] = true; - } - } + for (const [b, p] of g[a]) { + const nw = w * p; + if (nw > dist[b]) { + dist[b] = nw; + pq.enqueue([nw, b]); } } - return d[end]; } -}; + return dist[end_node]; +} ``` diff --git a/solution/1500-1599/1514.Path with Maximum Probability/Solution.cpp b/solution/1500-1599/1514.Path with Maximum Probability/Solution.cpp index 42180e06f87e2..a91fb762f7257 100644 --- a/solution/1500-1599/1514.Path with Maximum Probability/Solution.cpp +++ b/solution/1500-1599/1514.Path with Maximum Probability/Solution.cpp @@ -1,32 +1,32 @@ class Solution { public: - double maxProbability(int n, vector>& edges, vector& succProb, int start, int end) { - vector>> g(n); + double maxProbability(int n, vector>& edges, vector& succProb, int start_node, int end_node) { + using pdi = pair; + vector g[n]; for (int i = 0; i < edges.size(); ++i) { int a = edges[i][0], b = edges[i][1]; - double s = succProb[i]; - g[a].push_back({b, s}); - g[b].push_back({a, s}); + double p = succProb[i]; + g[a].emplace_back(p, b); + g[b].emplace_back(p, a); } - vector d(n); - d[start] = 1.0; - queue> q; - q.push({1.0, start}); - while (!q.empty()) { - auto p = q.front(); - q.pop(); - double w = p.first; - int u = p.second; - if (d[u] > w) continue; - for (auto& e : g[u]) { - int v = e.first; - double t = e.second; - if (d[v] < d[u] * t) { - d[v] = d[u] * t; - q.push({d[v], v}); + vector dist(n); + dist[start_node] = 1; + priority_queue pq; + pq.emplace(1, start_node); + while (!pq.empty()) { + auto [w, a] = pq.top(); + pq.pop(); + if (dist[a] > w) { + continue; + } + for (auto [p, b] : g[a]) { + auto nw = w * p; + if (nw > dist[b]) { + dist[b] = nw; + pq.emplace(nw, b); } } } - return d[end]; + return dist[end_node]; } -}; \ No newline at end of file +}; diff --git a/solution/1500-1599/1514.Path with Maximum Probability/Solution.go b/solution/1500-1599/1514.Path with Maximum Probability/Solution.go index 9cd309abefb40..dfc0760e3548e 100644 --- a/solution/1500-1599/1514.Path with Maximum Probability/Solution.go +++ b/solution/1500-1599/1514.Path with Maximum Probability/Solution.go @@ -1,34 +1,39 @@ -func maxProbability(n int, edges [][]int, succProb []float64, start int, end int) float64 { +func maxProbability(n int, edges [][]int, succProb []float64, start_node int, end_node int) float64 { g := make([][]pair, n) for i, e := range edges { - a, b, s := e[0], e[1], succProb[i] - g[a] = append(g[a], pair{b, s}) - g[b] = append(g[b], pair{a, s}) + a, b := e[0], e[1] + p := succProb[i] + g[a] = append(g[a], pair{p, b}) + g[b] = append(g[b], pair{p, a}) } - d := make([]float64, n) - d[start] = 1 - vis := make([]bool, n) - q := []int{start} - vis[start] = true - for len(q) > 0 { - i := q[0] - q = q[1:] - vis[i] = false - for _, ne := range g[i] { - j, s := ne.idx, ne.s - if d[j] < d[i]*s { - d[j] = d[i] * s - if !vis[j] { - q = append(q, j) - vis[j] = true - } + pq := hp{{1, start_node}} + dist := make([]float64, n) + dist[start_node] = 1 + for len(pq) > 0 { + p := heap.Pop(&pq).(pair) + w, a := p.p, p.a + if dist[a] > w { + continue + } + for _, e := range g[a] { + b, p := e.a, e.p + if nw := w * p; nw > dist[b] { + dist[b] = nw + heap.Push(&pq, pair{nw, b}) } } } - return d[end] + return dist[end_node] } type pair struct { - idx int - s float64 -} \ No newline at end of file + p float64 + a int +} +type hp []pair + +func (h hp) Len() int { return len(h) } +func (h hp) Less(i, j int) bool { return h[i].p > h[j].p } +func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } +func (h *hp) Push(x any) { *h = append(*h, x.(pair)) } +func (h *hp) Pop() (x any) { a := *h; x = a[len(a)-1]; *h = a[:len(a)-1]; return } diff --git a/solution/1500-1599/1514.Path with Maximum Probability/Solution.java b/solution/1500-1599/1514.Path with Maximum Probability/Solution.java index 2e8d1111abd32..c07a4aa4ac534 100644 --- a/solution/1500-1599/1514.Path with Maximum Probability/Solution.java +++ b/solution/1500-1599/1514.Path with Maximum Probability/Solution.java @@ -1,32 +1,37 @@ class Solution { - public double maxProbability(int n, int[][] edges, double[] succProb, int start, int end) { + public double maxProbability( + int n, int[][] edges, double[] succProb, int start_node, int end_node) { List>[] g = new List[n]; Arrays.setAll(g, k -> new ArrayList<>()); for (int i = 0; i < edges.length; ++i) { - int a = edges[i][0], b = edges[i][1]; - double s = succProb[i]; - g[a].add(new Pair<>(b, s)); - g[b].add(new Pair<>(a, s)); + var e = edges[i]; + int a = e[0], b = e[1]; + double p = succProb[i]; + g[a].add(new Pair<>(b, p)); + g[b].add(new Pair<>(a, p)); } - PriorityQueue> q - = new PriorityQueue<>(Comparator.comparingDouble(Pair::getKey)); - double[] d = new double[n]; - d[start] = 1.0; - q.offer(new Pair<>(-1.0, start)); - while (!q.isEmpty()) { - Pair p = q.poll(); - double w = p.getKey(); - w *= -1; - int u = p.getValue(); - for (Pair ne : g[u]) { - int v = ne.getKey(); - double t = ne.getValue(); - if (d[v] < d[u] * t) { - d[v] = d[u] * t; - q.offer(new Pair<>(-d[v], v)); + double[] dist = new double[n]; + dist[start_node] = 1; + PriorityQueue> pq + = new PriorityQueue<>(Comparator.comparingDouble(p -> - p.getValue())); + pq.offer(new Pair<>(start_node, 1.0)); + while (!pq.isEmpty()) { + var p = pq.poll(); + int a = p.getKey(); + double w = p.getValue(); + if (dist[a] > w) { + continue; + } + for (var e : g[a]) { + int b = e.getKey(); + double pab = e.getValue(); + double wab = w * pab; + if (wab > dist[b]) { + dist[b] = wab; + pq.offer(new Pair<>(b, wab)); } } } - return d[end]; + return dist[end_node]; } -} \ No newline at end of file +} diff --git a/solution/1500-1599/1514.Path with Maximum Probability/Solution.py b/solution/1500-1599/1514.Path with Maximum Probability/Solution.py index 83a0d71fddfe4..7a807b876a616 100644 --- a/solution/1500-1599/1514.Path with Maximum Probability/Solution.py +++ b/solution/1500-1599/1514.Path with Maximum Probability/Solution.py @@ -4,23 +4,23 @@ def maxProbability( n: int, edges: List[List[int]], succProb: List[float], - start: int, - end: int, + start_node: int, + end_node: int, ) -> float: - g = defaultdict(list) - for (a, b), s in zip(edges, succProb): - g[a].append((b, s)) - g[b].append((a, s)) - q = [(-1, start)] - d = [0] * n - d[start] = 1 - while q: - w, u = heappop(q) + g: List[List[Tuple[int, float]]] = [[] for _ in range(n)] + for (a, b), p in zip(edges, succProb): + g[a].append((b, p)) + g[b].append((a, p)) + pq = [(-1, start_node)] + dist = [0] * n + dist[start_node] = 1 + while pq: + w, a = heappop(pq) w = -w - if d[u] > w: + if dist[a] > w: continue - for v, t in g[u]: - if d[v] < d[u] * t: - d[v] = d[u] * t - heappush(q, (-d[v], v)) - return d[end] + for b, p in g[a]: + if (t := w * p) > dist[b]: + dist[b] = t + heappush(pq, (-t, b)) + return dist[end_node] diff --git a/solution/1500-1599/1514.Path with Maximum Probability/Solution.ts b/solution/1500-1599/1514.Path with Maximum Probability/Solution.ts new file mode 100644 index 0000000000000..7dbd8ea21567f --- /dev/null +++ b/solution/1500-1599/1514.Path with Maximum Probability/Solution.ts @@ -0,0 +1,32 @@ +function maxProbability( + n: number, + edges: number[][], + succProb: number[], + start_node: number, + end_node: number, +): number { + const pq = new MaxPriorityQueue({ priority: v => v[0] }); + const g: [number, number][][] = Array.from({ length: n }, () => []); + for (let i = 0; i < edges.length; ++i) { + const [a, b] = edges[i]; + g[a].push([b, succProb[i]]); + g[b].push([a, succProb[i]]); + } + const dist = Array.from({ length: n }, () => 0); + dist[start_node] = 1; + pq.enqueue([1, start_node]); + while (!pq.isEmpty()) { + const [w, a] = pq.dequeue().element; + if (dist[a] > w) { + continue; + } + for (const [b, p] of g[a]) { + const nw = w * p; + if (nw > dist[b]) { + dist[b] = nw; + pq.enqueue([nw, b]); + } + } + } + return dist[end_node]; +} diff --git a/solution/1500-1599/1514.Path with Maximum Probability/Solution2.cpp b/solution/1500-1599/1514.Path with Maximum Probability/Solution2.cpp deleted file mode 100644 index 0dde5981953d1..0000000000000 --- a/solution/1500-1599/1514.Path with Maximum Probability/Solution2.cpp +++ /dev/null @@ -1,34 +0,0 @@ -class Solution { -public: - double maxProbability(int n, vector>& edges, vector& succProb, int start, int end) { - vector>> g(n); - for (int i = 0; i < edges.size(); ++i) { - int a = edges[i][0], b = edges[i][1]; - double s = succProb[i]; - g[a].push_back({b, s}); - g[b].push_back({a, s}); - } - vector d(n); - vector vis(n); - d[start] = 1.0; - queue q{{start}}; - vis[start] = true; - while (!q.empty()) { - int i = q.front(); - q.pop(); - vis[i] = false; - for (auto& ne : g[i]) { - int j = ne.first; - double s = ne.second; - if (d[j] < d[i] * s) { - d[j] = d[i] * s; - if (!vis[j]) { - q.push(j); - vis[j] = true; - } - } - } - } - return d[end]; - } -}; \ No newline at end of file diff --git a/solution/1500-1599/1514.Path with Maximum Probability/Solution2.java b/solution/1500-1599/1514.Path with Maximum Probability/Solution2.java deleted file mode 100644 index 57209b5876d90..0000000000000 --- a/solution/1500-1599/1514.Path with Maximum Probability/Solution2.java +++ /dev/null @@ -1,34 +0,0 @@ -class Solution { - public double maxProbability(int n, int[][] edges, double[] succProb, int start, int end) { - List>[] g = new List[n]; - Arrays.setAll(g, k -> new ArrayList<>()); - for (int i = 0; i < edges.length; ++i) { - int a = edges[i][0], b = edges[i][1]; - double s = succProb[i]; - g[a].add(new Pair<>(b, s)); - g[b].add(new Pair<>(a, s)); - } - double[] d = new double[n]; - d[start] = 1.0; - boolean[] vis = new boolean[n]; - Deque q = new ArrayDeque<>(); - q.offer(start); - vis[start] = true; - while (!q.isEmpty()) { - int i = q.poll(); - vis[i] = false; - for (Pair ne : g[i]) { - int j = ne.getKey(); - double s = ne.getValue(); - if (d[j] < d[i] * s) { - d[j] = d[i] * s; - if (!vis[j]) { - q.offer(j); - vis[j] = true; - } - } - } - } - return d[end]; - } -} \ No newline at end of file diff --git a/solution/1500-1599/1514.Path with Maximum Probability/Solution2.py b/solution/1500-1599/1514.Path with Maximum Probability/Solution2.py deleted file mode 100644 index 1e7d863d8221c..0000000000000 --- a/solution/1500-1599/1514.Path with Maximum Probability/Solution2.py +++ /dev/null @@ -1,28 +0,0 @@ -class Solution: - def maxProbability( - self, - n: int, - edges: List[List[int]], - succProb: List[float], - start: int, - end: int, - ) -> float: - g = defaultdict(list) - for (a, b), s in zip(edges, succProb): - g[a].append((b, s)) - g[b].append((a, s)) - d = [0] * n - vis = [False] * n - d[start] = 1 - q = deque([start]) - vis[start] = True - while q: - i = q.popleft() - vis[i] = False - for j, s in g[i]: - if d[j] < d[i] * s: - d[j] = d[i] * s - if not vis[j]: - q.append(j) - vis[j] = True - return d[end] diff --git a/solution/3200-3299/3266.Final Array State After K Multiplication Operations II/README.md b/solution/3200-3299/3266.Final Array State After K Multiplication Operations II/README.md index a733a013ef8af..d72a8b5d71c87 100644 --- a/solution/3200-3299/3266.Final Array State After K Multiplication Operations II/README.md +++ b/solution/3200-3299/3266.Final Array State After K Multiplication Operations II/README.md @@ -325,7 +325,7 @@ func (h hp) Len() int { return len(h) } func (h hp) Less(i, j int) bool { return h[i].x < h[j].x || h[i].x == h[j].x && h[i].i < h[j].i } func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } func (h *hp) Push(x any) { *h = append(*h, x.(pair)) } -func (h *hp) Pop() any { a := *h; x := a[len(a)-1]; *h = a[:len(a)-1]; return x } +func (h *hp) Pop() (x any) { a := *h; x = a[len(a)-1]; *h = a[:len(a)-1]; return x } ``` diff --git a/solution/3200-3299/3266.Final Array State After K Multiplication Operations II/README_EN.md b/solution/3200-3299/3266.Final Array State After K Multiplication Operations II/README_EN.md index c07c67da62c33..21fecd620c26d 100644 --- a/solution/3200-3299/3266.Final Array State After K Multiplication Operations II/README_EN.md +++ b/solution/3200-3299/3266.Final Array State After K Multiplication Operations II/README_EN.md @@ -323,7 +323,7 @@ func (h hp) Len() int { return len(h) } func (h hp) Less(i, j int) bool { return h[i].x < h[j].x || h[i].x == h[j].x && h[i].i < h[j].i } func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } func (h *hp) Push(x any) { *h = append(*h, x.(pair)) } -func (h *hp) Pop() any { a := *h; x := a[len(a)-1]; *h = a[:len(a)-1]; return x } +func (h *hp) Pop() (x any) { a := *h; x = a[len(a)-1]; *h = a[:len(a)-1]; return x } ``` diff --git a/solution/3200-3299/3266.Final Array State After K Multiplication Operations II/Solution.go b/solution/3200-3299/3266.Final Array State After K Multiplication Operations II/Solution.go index 4ca706435acf2..ff719cdf7746f 100644 --- a/solution/3200-3299/3266.Final Array State After K Multiplication Operations II/Solution.go +++ b/solution/3200-3299/3266.Final Array State After K Multiplication Operations II/Solution.go @@ -46,7 +46,7 @@ type pair struct{ x, i int } type hp []pair func (h hp) Len() int { return len(h) } -func (h hp) Less(i, j int) bool { return h[i].x < h[j].x } +func (h hp) Less(i, j int) bool { return h[i].x < h[j].x || h[i].x == h[j].x && h[i].i < h[j].i } func (h hp) Swap(i, j int) { h[i], h[j] = h[j], h[i] } func (h *hp) Push(x any) { *h = append(*h, x.(pair)) } -func (h *hp) Pop() (x any) { a := *h; x := a[len(a)-1]; *h = a[:len(a)-1]; return } +func (h *hp) Pop() (x any) { a := *h; x = a[len(a)-1]; *h = a[:len(a)-1]; return x } diff --git a/solution/3300-3399/3367.Maximize Sum of Weights after Edge Removals/README.md b/solution/3300-3399/3367.Maximize Sum of Weights after Edge Removals/README.md index 87581dcd8f3cb..6653c6e4267b6 100644 --- a/solution/3300-3399/3367.Maximize Sum of Weights after Edge Removals/README.md +++ b/solution/3300-3399/3367.Maximize Sum of Weights after Edge Removals/README.md @@ -186,7 +186,7 @@ public: } } ranges::sort(t, greater<>()); - for (int i = 0; i < min((int)t.size(), k - 1); ++i) { + for (int i = 0; i < min((int) t.size(), k - 1); ++i) { s += t[i]; } return {s + (t.size() >= k ? t[k - 1] : 0), s}; diff --git a/solution/3300-3399/3367.Maximize Sum of Weights after Edge Removals/README_EN.md b/solution/3300-3399/3367.Maximize Sum of Weights after Edge Removals/README_EN.md index 8cd36fa3bc59d..358158b9ff93f 100644 --- a/solution/3300-3399/3367.Maximize Sum of Weights after Edge Removals/README_EN.md +++ b/solution/3300-3399/3367.Maximize Sum of Weights after Edge Removals/README_EN.md @@ -183,7 +183,7 @@ public: } } ranges::sort(t, greater<>()); - for (int i = 0; i < min((int)t.size(), k - 1); ++i) { + for (int i = 0; i < min((int) t.size(), k - 1); ++i) { s += t[i]; } return {s + (t.size() >= k ? t[k - 1] : 0), s}; diff --git a/solution/3300-3399/3367.Maximize Sum of Weights after Edge Removals/Solution.cpp b/solution/3300-3399/3367.Maximize Sum of Weights after Edge Removals/Solution.cpp index 48cf22ddb49ba..043b0f4aac007 100644 --- a/solution/3300-3399/3367.Maximize Sum of Weights after Edge Removals/Solution.cpp +++ b/solution/3300-3399/3367.Maximize Sum of Weights after Edge Removals/Solution.cpp @@ -24,7 +24,7 @@ class Solution { } } ranges::sort(t, greater<>()); - for (int i = 0; i < min((int)t.size(), k - 1); ++i) { + for (int i = 0; i < min((int) t.size(), k - 1); ++i) { s += t[i]; } return {s + (t.size() >= k ? t[k - 1] : 0), s};