原创 - 重新规划路线 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;
};