返回介绍

solution / 1500-1599 / 1514.Path with Maximum Probability / README

发布于 2024-06-17 01:03:18 字数 8616 浏览 0 评论 0 收藏 0

1514. 概率最大的路径

English Version

题目描述

给你一个由 n 个节点(下标从 0 开始)组成的无向加权图,该图由一个描述边的列表组成,其中 edges[i] = [a, b] 表示连接节点 a 和 b 的一条无向边,且该边遍历成功的概率为 succProb[i]

指定两个节点分别作为起点 start 和终点 end ,请你找出从起点到终点成功概率最大的路径,并返回其成功概率。

如果不存在从 startend 的路径,请 返回 0 。只要答案与标准答案的误差不超过 1e-5 ,就会被视作正确答案。

 

示例 1:

输入:n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.2], start = 0, end = 2
输出:0.25000
解释:从起点到终点有两条路径,其中一条的成功概率为 0.2 ,而另一条为 0.5 * 0.5 = 0.25

示例 2:

输入:n = 3, edges = [[0,1],[1,2],[0,2]], succProb = [0.5,0.5,0.3], start = 0, end = 2
输出:0.30000

示例 3:

输入:n = 3, edges = [[0,1]], succProb = [0.5], start = 0, end = 2
输出:0.00000
解释:节点 0 和 节点 2 之间不存在路径

 

提示:

  • 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
  • 每两个节点之间最多有一条边

解法

方法一:堆优化 Dijkstra 算法

时间复杂度 O(mlogn)。

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))
    q = [(-1, start)]
    d = [0] * n
    d[start] = 1
    while q:
      w, u = heappop(q)
      w = -w
      if d[u] > 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]
class Solution {
  public double maxProbability(int n, int[][] edges, double[] succProb, int start, int end) {
    List<Pair<Integer, Double>>[] 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));
    }
    PriorityQueue<Pair<Double, Integer>> 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<Double, Integer> p = q.poll();
      double w = p.getKey();
      w *= -1;
      int u = p.getValue();
      for (Pair<Integer, Double> 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));
        }
      }
    }
    return d[end];
  }
}
class Solution {
public:
  double maxProbability(int n, vector<vector<int>>& edges, vector<double>& succProb, int start, int end) {
    vector<vector<pair<int, double>>> 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<double> d(n);
    d[start] = 1.0;
    queue<pair<double, int>> 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});
        }
      }
    }
    return d[end];
  }
};
func maxProbability(n int, edges [][]int, succProb []float64, start int, end 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})
  }
  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
        }
      }
    }
  }
  return d[end]
}

type pair struct {
  idx int
  s   float64
}

方法二:SPFA 算法

时间复杂度,平均情况下 O(m),最坏情况下 O(nm),n 表示点数,m 表示边数。

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]
class Solution {
  public double maxProbability(int n, int[][] edges, double[] succProb, int start, int end) {
    List<Pair<Integer, Double>>[] 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<Integer> q = new ArrayDeque<>();
    q.offer(start);
    vis[start] = true;
    while (!q.isEmpty()) {
      int i = q.poll();
      vis[i] = false;
      for (Pair<Integer, Double> 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];
  }
}
class Solution {
public:
  double maxProbability(int n, vector<vector<int>>& edges, vector<double>& succProb, int start, int end) {
    vector<vector<pair<int, double>>> 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<double> d(n);
    vector<bool> vis(n);
    d[start] = 1.0;
    queue<int> 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];
  }
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文