原创 - 重新规划路线 BFS+邻接表 解释

重新规划路线

n 座城市,从 0 到 n-1 编号,其间共有 n-1 条路线。因此,要想在两座不同城市之间旅行只有唯一一条路线可供选择(路线网形成一颗树)。去年,交通运输部决定重新规划路线,以改变交通拥堵的状况。

路线用 connections 表示,其中 connections[i] = [a, b] 表示从城市 a 到 b 的一条有向路线。
今年,城市 0 将会举办一场大型比赛,很多游客都想前往城市 0 。

请你帮助重新规划路线方向,使每个城市都可以访问城市 0 。返回需要变更方向的最小路线数。
题目数据 保证 每个城市在重新规划路线方向后都能到达城市 0 。

n = 6, connections = [[0,1],[1,3],[2,3],[4,0],[4,5]]
3

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reorder-routes-to-make-all-paths-lead-to-the-city-zero

思路

目的是遍历所有的点,把不指向0点的路径都记录下来,这样的路径和就是答案。

做法

建议一个邻接表,其中每个点保存的是和他有关联的点,cost根据后面的需要设定。
对于(u, v)有:

  • u:[v, cost]
  • v: [u, cost]

BFS从0点开始遍历,得出结果。

在遍历的时候我们查找的是u: [v, cost], 我们希望可以从v到达u所以u: [v, cost]中cost为1(需要改变方向)。同理v: [u, 0]

所以在构造邻接表时,对于(u, v)有:

  • u: [v, 1]
  • v: [u, 0]

在调整完与0点相连的路线后,我们依次调整与(可以通向0点的点)相连的点,这里使用队列来处理。

(可以通向0点的点)相连的点,包括我们处理过点,当处理我们已经处理的过的点时,我们选择跳过。使用数组来表示处理过的点。


/**
 * @param {number} n
 * @param {number[][]} connections
 * @return {number}
 */
var minReorder = function (n, connections) {
  let map = {};
  // 建立一个邻接表,其中每个点保存的是和他有关联的点,cost根据题目需要设定。
  // 对于 (u, v)有: u:[v, cost]  v:[u, cost]
  // 我们从u开始遍历,对于(u, v)我们希望v可以到达u,所以
  // u:[v, 1]需要改变方向, v:[u, 0]不需要改变方向
  for (let i = 0; i < connections.length; i++) {
    let [city1, city2] = connections[i];
    if (map[city1]) map[city1].push([city2, 1]);
    else map[city1] = [[city2, 1]];
    if (map[city2]) map[city2].push([city1, 0]);
    else map[city2] = [[city1, 0]];
  }
  let queue = [0]; // 我们想要通往的城市
  let seen = new Array(n).fill(false); // 我们处理过的城市
  let ans = 0;
  // 要想保证都能到达城市0,就需要与0连接的城市都能达到城市0, (与可以到达城市0的城市)相连的城市可以到达(与可以到达城市0的城市)
  while (queue.length) {
    let top = queue.shift();
    seen[top] = true;
    // 查找与top相连的城市,对于已经处理过的城市跳过处理。
    for (let [city, cost] of map[top]) {
      if (seen[city]) continue;
      ans += cost;
      queue.push(city);
    }
  }
  return ans;
};

原文地址: https://www.cnblogs.com/xiaoxu-xmy/p/13791742.html

posted @ 2020-10-10 12:04  lemon-Xu  阅读(183)  评论(0编辑  收藏  举报