815. 公交路线

给你一个数组 routes ,表示一系列公交线路,其中每个 routes[i] 表示一条公交线路,第 i 辆公交车将会在上面循环行驶。

  • 例如,路线 routes[0] = [1, 5, 7] 表示第 0 辆公交车会一直按序列 1 -> 5 -> 7 -> 1 -> 5 -> 7 -> 1 -> … 这样的车站路线行驶。

现在从 source 车站出发(初始时不在公交车上),要前往 target 车站。 期间仅可乘坐公交车。
求出 最少乘坐的公交车数量 。如果不可能到达终点车站,返回 -1 。

示例 1:
输入:routes = [[1,2,7],[3,6,7]], source = 1, target = 6 输出:2 解释:最优策略是先乘坐第一辆公交车到达车站 7 , 然后换乘第二辆公交车到车站 6 。
示例 2:
输入:routes = [[7,12],[4,5,15],[6],[15,19],[9,12,13]], source = 15, target = 12 输出:-1

提示:

  • 1 <= routes.length <= 500.
  • 1 <= routes[i].length <= 105
  • routes[i] 中的所有值 互不相同
  • sum(routes[i].length) <= 105
  • 0 <= routes[i][j] < 106
  • 0 <= source, target < 106

思路:
如何建图?
考虑将每条公交路线看作一个点
即找从所有包含源点公交站的公交路线到所有包含终点公交站的所有公交路线的最短距离
只要任意两条路线有相同的公交站,说明相互可达。

  1. class Solution {
  2. public int numBusesToDestination(int[][] routes, int source, int target) {
  3. int n = routes.length;
  4. if (source == target) return 0;
  5. boolean[][] st = new boolean[n][n];
  6. Map<Integer, List<Integer>> map = new HashMap<>();
  7. for (int i = 0; i < n; i++) {
  8. for (int x : routes[i]) {
  9. List<Integer> t = map.getOrDefault(x, new ArrayList<>());
  10. for (int j : t) {
  11. st[i][j] = st[j][i] = true;
  12. }
  13. t.add(i);
  14. map.put(x, t);
  15. }
  16. }
  17. int[] d = new int[n];
  18. Arrays.fill(d, 0x3f3f3f3f);
  19. Queue<Integer> q = new LinkedList<>();
  20. for (int x : map.get(source)) {
  21. d[x] = 1;
  22. q.offer(x);
  23. }
  24. while (!q.isEmpty()) {
  25. int u = q.poll();
  26. for (int i = 0; i < n; i++) {
  27. if (i == u) continue;
  28. if (st[i][u] && d[i] > d[u] + 1) {
  29. d[i] = d[u] + 1;
  30. q.offer(i);
  31. }
  32. }
  33. }
  34. int min = 0x3f3f3f3f;
  35. for (int x : map.getOrDefault(target, new ArrayList<>()))
  36. min = Math.min(min, d[x]);
  37. return min == 0x3f3f3f3f ? -1: min;
  38. }
  39. }

Acwing 3675. 逃离迷宫

image.png

思路:本质是单源最短路问题
不同点在于可将每条长或宽看作一个点,每条边为拐弯一次。

  1. import java.util.*;
  2. public class Main {
  3. static final int INF = 0x3f3f3f3f, N = 110;
  4. static int n, m;
  5. static char[][] c = new char[N][];
  6. static int[][] res = new int[N][N];
  7. static int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
  8. static boolean[][] st = new boolean[N][N];
  9. public static void main(String[] args) {
  10. Scanner sc = new Scanner(System.in);
  11. int T = sc.nextInt();
  12. while (T-- > 0) {
  13. n = sc.nextInt();
  14. m = sc.nextInt();
  15. for (int i = 1; i <= n; i++)
  16. c[i] = (" " + sc.next()).toCharArray();
  17. for (int i = 1; i <= n; i++) {
  18. Arrays.fill(res[i], 1, m + 1, INF);
  19. Arrays.fill(st[i], 1, m + 1, false);
  20. }
  21. int k = sc.nextInt();
  22. int sx, sy, ex, ey;
  23. sy = sc.nextInt();
  24. sx = sc.nextInt();
  25. ey = sc.nextInt();
  26. ex = sc.nextInt();
  27. res[sx][sy] = -1;
  28. Queue<int[]> q = new LinkedList<>();
  29. q.offer(new int[]{sx, sy, -1});
  30. st[sx][sy] = true;
  31. while (!q.isEmpty()) {
  32. int[] p = q.poll();
  33. int x = p[0], y = p[1], t = p[2];
  34. for (int i = 0; i < 4; i++) {
  35. int a = x + dx[i], b = y + dy[i];
  36. while (a >= 1 && a <= n && b >= 1 && b <= m && c[a][b] == '.') {
  37. if (!st[a][b]) {
  38. res[a][b] = t + 1;
  39. st[a][b] = true;
  40. q.offer(new int[]{a, b, t + 1});
  41. }
  42. a = a + dx[i];
  43. b = b + dy[i];
  44. }
  45. }
  46. }
  47. // for (int i = 1; i <= n; i++) {
  48. // for (int j = 1; j <= m; j++) {
  49. // System.out.printf("%-10d ", res[i][j]);
  50. // }
  51. // System.out.println();
  52. // }
  53. // System.out.println(res[ex][ey] + " " + k);
  54. if (res[ex][ey] <= k)
  55. System.out.println("yes");
  56. else System.out.println("no");
  57. }
  58. }
  59. }