[LeetCode] 1466. Reorder Routes to Make All Paths Lead to the City Zero

There are n cities numbered from 0 to n-1 and n-1 roads such that there is only one way to travel between two different cities (this network form a tree). Last year, The ministry of transport decided to orient the roads in one direction because they are too narrow.

Roads are represented by connections where connections[i] = [a, b] represents a road from city a to b.

This year, there will be a big event in the capital (city 0), and many people want to travel to this city.

Your task consists of reorienting some roads such that each city can visit the city 0. Return the minimum number of edges changed.

It's guaranteed that each city can reach the city 0 after reorder.

Example 1:

Input: n = 6, connections = [[0,1],[1,3],[2,3],[4,0],[4,5]]
Output: 3
Explanation: Change the direction of edges show in red such that each node can reach the node 0 (capital).

Example 2:

Input: n = 5, connections = [[1,0],[1,2],[3,2],[3,4]]
Output: 2
Explanation: Change the direction of edges show in red such that each node can reach the node 0 (capital).

Example 3:

Input: n = 3, connections = [[1,0],[2,0]]
Output: 0

Constraints:

  • 2 <= n <= 5 * 10^4
  • connections.length == n-1
  • connections[i].length == 2
  • 0 <= connections[i][0], connections[i][1] <= n-1
  • connections[i][0] != connections[i][1]

重新规划路线。

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

路线用 connections 表示,其中 connections[i] = [a, b] 表示从城市 a 到 b 的一条有向路线。

今年,城市 0 将会举办一场大型比赛,很多游客都想前往城市 0 。

请你帮助重新规划路线方向,使每个城市都可以访问城市 0 。返回需要变更方向的最小路线数。

题目数据 保证 每个城市在重新规划路线方向后都能到达城市 0 。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reorder-routes-to-make-all-paths-lead-to-the-city-zero
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这是一道图论的题。题意不难理解,注意题目中的一个重点。每两座城市之间只有一条 connection,并且路线网形成一棵树。题目问的是如何调整线路使得所有的城市最终都能抵达城市 0。这里我们可以反过来想,我们可以试着从城市 0 出发,看看是否可以根据已知的 connections 到达所有非 0 的城市。因为每两座城市之间一定有路线相连,只是有可能方向不合适,这里我提供两种实现,BFS 和DFS。

既然是图论的题,那么我们首先要做的还是创建图。我这里用 hashmap 把图创建好了之后,我们还需要一个 hashset 来存储一下所有的 connections。之后我们去做 BFS 遍历,对于每一个从 queue 中弹出的节点,我们遍历他的所有邻居节点 next。对于每一个 next 节点,我们判断的是

  • 这个城市是否被访问过 - 如果是则跳过
  • 如果没有被访问过,那么去 hashset 里看看是否存在一条方向相反的路线,若存在则需要调整其方向

其他的请参见代码注释。

BFS实现

时间O(V + E)

空间O(n)

Java实现

 1 class Solution {
 2     public int minReorder(int n, int[][] connections) {
 3         // 转译所有的connections
 4         HashSet<String> set = new HashSet<>();
 5         // create the graph
 6         HashMap<Integer, HashSet<Integer>> map = new HashMap<>();
 7         for (int[] c : connections) {
 8             set.add(c[0] + "," + c[1]);
 9             // map.computeIfAbsent(c[0], k -> new HashSet<>());
10             // map.computeIfAbsent(c[1], k -> new HashSet<>());
11             if (!map.containsKey(c[0])) {
12                 map.put(c[0], new HashSet<>());
13             }
14             map.get(c[0]).add(c[1]);
15             if (!map.containsKey(c[1])) {
16                 map.put(c[1], new HashSet<>());
17             }
18             map.get(c[1]).add(c[0]);
19         }
20 
21         // res - 需要调整的线路数量
22         int res = 0;
23         Queue<Integer> queue = new LinkedList<>();
24         queue.offer(0);
25         boolean[] visited = new boolean[n];
26         visited[0] = true;
27         while (!queue.isEmpty()) {
28             int cur = queue.poll();
29             for (int next : map.getOrDefault(cur, new HashSet<>())) {
30                 // 如果下一个城市已经访问过,则跳过
31                 if (visited[next] == true) {
32                     continue;
33                 }
34                 visited[next] = true;
35                 // 如果hashset存在一条相反的线路,说明需要调整,则res++
36                 if (!set.contains(next + "," + cur)) {
37                     res++;
38                 }
39                 queue.offer(next);
40             }
41         }
42         return res;
43     }
44 }

 

DFS实现

时间O(V + E)

空间O(n)

Java实现

 1 class Solution {
 2     Set<String> set = new HashSet<>();
 3     int res = 0;
 4     public int minReorder(int n, int[][] connections) {
 5         List<List<Integer>> g = buildGraph(n, connections);
 6         boolean[] visited = new boolean[n];
 7         dfs(g, visited, 0);
 8         return res;
 9     }
10 
11     private void dfs(List<List<Integer>> g, boolean[] visited, int cur) {
12         visited[cur] = true;
13         for (int next : g.get(cur)) {
14             if (visited[next]) {
15                 continue;
16             }
17             if (set.contains(cur + "," + next)) {
18                 res++;
19             }
20             dfs(g, visited, next);
21         }
22     }
23 
24     private List<List<Integer>> buildGraph(int n, int[][] connections) {
25         List<List<Integer>> g = new ArrayList<>();
26         for (int i = 0; i < n; i++) {
27             g.add(new ArrayList<>());
28         }
29         for (int[] c : connections) {
30             int from = c[0];
31             int to = c[1];
32             g.get(from).add(to);
33             g.get(to).add(from);
34             set.add(from + "," + to);
35         }
36         return g;
37     }
38 }

 

LeetCode 题目总结

posted @ 2021-05-18 00:46  CNoodle  阅读(457)  评论(0编辑  收藏  举报