-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path1514-PathWithMaximumProbability.go
More file actions
148 lines (130 loc) · 5.21 KB
/
1514-PathWithMaximumProbability.go
File metadata and controls
148 lines (130 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package main
// 1514. Path with Maximum Probability
// You are given an undirected weighted graph of n nodes (0-indexed),
// represented by an edge list where edges[i] = [a, b] is an undirected edge connecting the nodes a
// and b with a probability of success of traversing that edge succProb[i].
// Given two nodes start and end, find the path with the maximum probability of success to go from start to end
// and return its success probability.
// If there is no path from start to end, return 0.
// Your answer will be accepted if it differs from the correct answer by at most 1e-5.
// Example 1:
// <img src="https://assets.leetcode.com/uploads/2019/09/20/1558_ex1.png" />
// Input: n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.2], start = 0, end = 2
// Output: 0.25000
// Explanation: There are two paths from start to end, one having a probability of success = 0.2 and the other has 0.5 * 0.5 = 0.25.
// Example 2:
// <img src="https://assets.leetcode.com/uploads/2019/09/20/1558_ex2.png" />
// Input: n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.3], start = 0, end = 2
// Output: 0.30000
// Example 3:
// <img src="https://assets.leetcode.com/uploads/2019/09/20/1558_ex3.png" />
// Input: n = 3, edges = [[0,1]], succProb = [0.5], start = 0, end = 2
// Output: 0.00000
// Explanation: There is no path between 0 and 2.
// Constraints:
// 2 <= n <= 10^4
// 0 <= start, end < n
// start != end
// 0 <= a, b < n
// a != b
// 0 <= succProb.length == edges.length <= 2*10^4
// 0 <= succProb[i] <= 1
// There is at most one edge between every two nodes.
import "fmt"
import "container/heap"
import "math"
type Edge struct {
to int
weight float64
}
type Node struct {
node int
weight float64
}
type PriorityQueue []*Node
func (pq PriorityQueue) Len() int { return len(pq) }
func (pq PriorityQueue) Less(i, j int) bool { return pq[i].weight > pq[j].weight }
func (pq PriorityQueue) Swap(i, j int) { pq[i], pq[j] = pq[j], pq[i] }
func (pq *PriorityQueue) Push(x interface{}) {
*pq = append(*pq, x.(*Node))
}
func (pq *PriorityQueue) Pop() interface{} {
old := *pq
n := len(old)
x := old[n-1]
*pq = old[0 : n-1]
return x
}
func maxProbability(n int, edges [][]int, succProb []float64, start int, end int) float64 {
graph := make([][]Edge, n)
for i, edge := range edges {
graph[edge[0]] = append(graph[edge[0]], Edge{edge[1], math.Log(succProb[i])})
graph[edge[1]] = append(graph[edge[1]], Edge{edge[0], math.Log(succProb[i])})
}
dist := make([]float64, n)
for i := range dist {
dist[i] = math.Inf(-1)
}
dist[start] = 0
pq := PriorityQueue{}
heap.Push(&pq, &Node{start, 0})
for pq.Len() > 0 {
curr := heap.Pop(&pq).(*Node)
if curr.node == end {
return math.Exp(dist[end])
}
if curr.weight < dist[curr.node] {
continue
}
for _, edge := range graph[curr.node] {
if nextDist := dist[curr.node] + edge.weight; nextDist > dist[edge.to] {
dist[edge.to] = nextDist
heap.Push(&pq, &Node{edge.to, nextDist})
}
}
}
return 0
}
func maxProbability1(n int, edges [][]int, succProb []float64, start_node int, end_node int) float64 {
dp := make([]float64, n)
dp[start_node] = 1.0
for {
k := false
for j := 0; j < len(edges); j++ {
if dp[edges[j][0]] * succProb[j] > dp[edges[j][1]] {
dp[edges[j][1]] = dp[edges[j][0]] * succProb[j]
k = true
}
if dp[edges[j][1]] * succProb[j] > dp[edges[j][0]] {
dp[edges[j][0]] = dp[edges[j][1]] * succProb[j]
k = true
}
}
if !k {
break
}
}
return dp[end_node]
}
func main() {
// Example 1:
// <img src="https://assets.leetcode.com/uploads/2019/09/20/1558_ex1.png" />
// Input: n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.2], start = 0, end = 2
// Output: 0.25000
// Explanation: There are two paths from start to end, one having a probability of success = 0.2 and the other has 0.5 * 0.5 = 0.25.
fmt.Println(maxProbability(3,[][]int{{0,1},{1,2},{0,2}}, []float64{0.5,0.5,0.2}, 0, 2)) // 0.25000
// Example 2:
// <img src="https://assets.leetcode.com/uploads/2019/09/20/1558_ex2.png" />
// Input: n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.3], start = 0, end = 2
// Output: 0.30000
fmt.Println(maxProbability(3,[][]int{{0,1},{1,2},{0,2}}, []float64{0.5,0.5,0.3}, 0, 2)) // 0.30000
// Example 3:
// <img src="https://assets.leetcode.com/uploads/2019/09/20/1558_ex3.png" />
// Input: n = 3, edges = [[0,1]], succProb = [0.5], start = 0, end = 2
// Output: 0.00000
// Explanation: There is no path between 0 and 2.
fmt.Println(maxProbability(3,[][]int{{0,1}}, []float64{0.5}, 0, 2)) // 0.00000
fmt.Println(maxProbability1(3,[][]int{{0,1},{1,2},{0,2}}, []float64{0.5,0.5,0.2}, 0, 2)) // 0.25000
fmt.Println(maxProbability1(3,[][]int{{0,1},{1,2},{0,2}}, []float64{0.5,0.5,0.3}, 0, 2)) // 0.30000
fmt.Println(maxProbability1(3,[][]int{{0,1}}, []float64{0.5}, 0, 2)) // 0.00000
}