返回介绍

solution / 1000-1099 / 1059.All Paths from Source Lead to Destination / README

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

1059. 从始点到终点的所有路径

English Version

题目描述

给定有向图的边 edges,以及该图的始点 source 和目标终点 destination,确定从始点 source 出发的所有路径是否最终结束于目标终点 destination,即:

  • 从始点 source 到目标终点 destination 存在至少一条路径
  • 如果存在从始点 source 到没有出边的节点的路径,则该节点就是路径终点。
  • 从始点source到目标终点 destination 可能路径数是有限数字

当从始点 source 出发的所有路径都可以到达目标终点 destination 时返回 true,否则返回 false

 

示例 1:

输入:n = 3, edges = [[0,1],[0,2]], source = 0, destination = 2
输出:false
说明:节点 1 和节点 2 都可以到达,但也会卡在那里。

示例 2:

输入:n = 4, edges = [[0,1],[0,3],[1,2],[2,1]], source = 0, destination = 3
输出:false
说明:有两种可能:在节点 3 处结束,或是在节点 1 和节点 2 之间无限循环。

示例 3:

输入:n = 4, edges = [[0,1],[0,2],[1,3],[2,3]], source = 0, destination = 3
输出:true

 

提示:

  • 1 <= n <= 104
  • 0 <= edges.length <= 104
  • edges.length == 2
  • 0 <= ai, bi <= n - 1
  • 0 <= source <= n - 1
  • 0 <= destination <= n - 1
  • 给定的图中可能带有自环和平行边。

解法

方法一:记忆化搜索

建图,然后从 source 出发,进行深度优先搜索:

如果遇到了 destination,判断此时是否还有出边,如果有出边,返回 false,否则返回 true

如果遇到了环(此前访问过),或者遇到了没有出边的节点,直接返回 false

否则,我们把当前节点标记为已访问,然后对当前节点的所有出边进行深度优先搜索,只要有一条路径无法可以到达 destination,就返回 false,否则返回 true

过程中我们用一个数组 $f$ 记录每个节点的状态,每个 $f[i]$ 的值有三种,分别表示:

  • 对于 $f[i] = 0$,表示节点 $i$ 未被访问;
  • 对于 $f[i] = 1$,表示节点 $i$ 已被访问,且可以到达 destination
  • 对于 $f[i] = 2$,表示节点 $i$ 已被访问,但无法到达 destination

时间复杂度 $O(n)$。其中 $n$ 为节点数。

class Solution:
  def leadsToDestination(
    self, n: int, edges: List[List[int]], source: int, destination: int
  ) -> bool:
    @cache
    def dfs(i):
      if i == destination:
        return not g[i]
      if i in vis or not g[i]:
        return False
      vis.add(i)
      for j in g[i]:
        if not dfs(j):
          return False
      return True

    g = defaultdict(list)
    for a, b in edges:
      g[a].append(b)
    vis = set()
    return dfs(source)
class Solution {
  private List<Integer>[] g;
  private int[] f;
  private boolean[] vis;
  private int k;

  public boolean leadsToDestination(int n, int[][] edges, int source, int destination) {
    vis = new boolean[n];
    g = new List[n];
    k = destination;
    f = new int[n];
    Arrays.setAll(g, key -> new ArrayList<>());
    for (var e : edges) {
      g[e[0]].add(e[1]);
    }
    return dfs(source);
  }

  private boolean dfs(int i) {
    if (i == k) {
      return g[i].isEmpty();
    }
    if (f[i] != 0) {
      return f[i] == 1;
    }
    if (vis[i] || g[i].isEmpty()) {
      return false;
    }
    vis[i] = true;
    for (int j : g[i]) {
      if (!dfs(j)) {
        f[i] = -1;
        return false;
      }
    }
    f[i] = 1;
    return true;
  }
}
class Solution {
public:
  bool leadsToDestination(int n, vector<vector<int>>& edges, int source, int destination) {
    vector<bool> vis(n);
    vector<vector<int>> g(n);
    vector<int> f(n);
    for (auto& e : edges) {
      g[e[0]].push_back(e[1]);
    }
    function<bool(int)> dfs = [&](int i) {
      if (i == destination) {
        return g[i].empty();
      }
      if (f[i]) {
        return f[i] == 1;
      }
      if (vis[i] || g[i].empty()) {
        return false;
      }
      vis[i] = true;
      for (int j : g[i]) {
        if (!dfs(j)) {
          f[i] = -1;
          return false;
        }
      }
      f[i] = 1;
      return true;
    };
    return dfs(source);
  }
};
func leadsToDestination(n int, edges [][]int, source int, destination int) bool {
  vis := make([]bool, n)
  g := make([][]int, n)
  f := make([]int, n)
  for _, e := range edges {
    g[e[0]] = append(g[e[0]], e[1])
  }
  var dfs func(int) bool
  dfs = func(i int) bool {
    if i == destination {
      return len(g[i]) == 0
    }
    if f[i] != 0 {
      return f[i] == 1
    }
    if vis[i] || len(g[i]) == 0 {
      return false
    }
    vis[i] = true
    for _, j := range g[i] {
      if !dfs(j) {
        f[i] = -1
        return false
      }
    }
    f[i] = 1
    return true
  }
  return dfs(source)
}

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

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

发布评论

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