100041. 可以到达每一个节点的最少边反转次数
给你一个 n
个点的 简单有向图 (没有重复边的有向图),节点编号为 0
到 n - 1
。如果这些边是双向边,那么这个图形成一棵 树 。
给你一个整数 n
和一个 二维 整数数组 edges
,其中 edges[i] = [ui, vi]
表示从节点 ui
到节点 vi
有一条 有向边 。
边反转 指的是将一条边的方向反转,也就是说一条从节点 ui
到节点 vi
的边会变为一条从节点 vi
到节点 ui
的边。
对于范围 [0, n - 1]
中的每一个节点 i
,你的任务是分别 独立 计算 最少 需要多少次 边反转 ,从节点 i
出发经过 一系列有向边 ,可以到达所有的节点。
请你返回一个长度为 n
的整数数组 answer
,其中 answer[i]
表示从节点 i
出发,可以到达所有节点的 最少边反转 次数。
示例 1:
输入:n = 4, edges = [[2,0],[2,1],[1,3]] 输出:[1,1,0,2] 解释:上图表示了与输入对应的简单有向图。 对于节点 0 :反转 [2,0] ,从节点 0 出发可以到达所有节点。 所以 answer[0] = 1 。 对于节点 1 :反转 [2,1] ,从节点 1 出发可以到达所有节点。 所以 answer[1] = 1 。 对于节点 2 :不需要反转就可以从节点 2 出发到达所有节点。 所以 answer[2] = 0 。 对于节点 3 :反转 [1,3] 和 [2,1] ,从节点 3 出发可以到达所有节点。 所以 answer[3] = 2 。
示例 2:
输入:n = 3, edges = [[1,2],[2,0]] 输出:[2,0,1] 解释:上图表示了与输入对应的简单有向图。 对于节点 0 :反转 [2,0] 和 [1,2] ,从节点 0 出发可以到达所有节点。 所以 answer[0] = 2 。 对于节点 1 :不需要反转就可以从节点 2 出发到达所有节点。 所以 answer[1] = 0 。 对于节点 2 :反转 [1,2] ,从节点 2 出发可以到达所有节点。 所以 answer[2] = 1 。
提示:
2 <= n <= 105
edges.length == n - 1
edges[i].length == 2
0 <= ui == edges[i][0] < n
0 <= vi == edges[i][1] < n
ui != vi
原站题解
javascript 解法, 执行用时: 780 ms, 内存消耗: 119.2 MB, 提交时间: 2023-09-17 22:34:09
/** * @param {number} n * @param {number[][]} edges * @return {number[]} */ var minEdgeReversals = function (n, edges) { const g = new Array(n).fill(null).map(() => []); for (const [x, y] of edges) { g[x].push([y, 1]); g[y].push([x, -1]); // 从 y 到 x 需要反向 } const ans = new Array(n).fill(0); function dfs(x, fa) { for (const [y, dir] of g[x]) { if (y !== fa) { ans[0] += dir < 0; dfs(y, x); } } } dfs(0, -1); function reroot(x, fa) { for (const [y, dir] of g[x]) { if (y !== fa) { ans[y] = ans[x] + dir; // dir 就是从 x 换到 y 的「变化量」 reroot(y, x); } } } reroot(0, -1); return ans; };
golang 解法, 执行用时: 256 ms, 内存消耗: 41.4 MB, 提交时间: 2023-09-17 22:33:52
func minEdgeReversals(n int, edges [][]int) (ans []int) { type pair struct{ to, dir int } g := make([][]pair, n) for _, e := range edges { x, y := e[0], e[1] g[x] = append(g[x], pair{y, 1}) g[y] = append(g[y], pair{x, -1}) // 从 y 到 x 需要反向 } ans = make([]int, n) var dfs func(int, int) dfs = func(x, fa int) { for _, e := range g[x] { y := e.to if y != fa { if e.dir < 0 { ans[0]++ } dfs(y, x) } } } dfs(0, -1) var reroot func(int, int) reroot = func(x, fa int) { for _, e := range g[x] { y := e.to if y != fa { ans[y] = ans[x] + e.dir // e.dir 就是从 x 换到 y 的「变化量」 reroot(y, x) } } } reroot(0, -1) return ans }
cpp 解法, 执行用时: 460 ms, 内存消耗: 207.4 MB, 提交时间: 2023-09-17 22:33:35
class Solution { public: vector<int> minEdgeReversals(int n, vector<vector<int>> &edges) { vector<vector<pair<int, int>>> g(n); for (auto &e: edges) { int x = e[0], y = e[1]; g[x].emplace_back(y, 1); g[y].emplace_back(x, -1); // 从 y 到 x 需要反向 } vector<int> ans(n, 0); function<void(int, int)> dfs = [&](int x, int fa) { for (auto &[y, dir]: g[x]) { if (y != fa) { ans[0] += dir < 0; dfs(y, x); } } }; dfs(0, -1); function<void(int, int)> reroot = [&](int x, int fa) { for (auto &[y, dir]: g[x]) { if (y != fa) { ans[y] = ans[x] + dir; // dir 就是从 x 换到 y 的「变化量」 reroot(y, x); } } }; reroot(0, -1); return ans; } };
java 解法, 执行用时: 53 ms, 内存消耗: 121.8 MB, 提交时间: 2023-09-17 22:33:23
class Solution { public int[] minEdgeReversals(int n, int[][] edges) { List<int[]>[] g = new ArrayList[n]; Arrays.setAll(g, e -> new ArrayList<>()); for (var e : edges) { int x = e[0], y = e[1]; g[x].add(new int[]{y, 1}); g[y].add(new int[]{x, -1}); // 从 y 到 x 需要反向 } var ans = new int[n]; dfs(0, -1, g, ans); reroot(0, -1, g, ans); return ans; } private void dfs(int x, int fa, List<int[]>[] g, int[] ans) { for (var e : g[x]) { int y = e[0], dir = e[1]; if (y != fa) { if (dir < 0) { ans[0]++; } dfs(y, x, g, ans); } } } private void reroot(int x, int fa, List<int[]>[] g, int[] ans) { for (var e : g[x]) { int y = e[0], dir = e[1]; if (y != fa) { ans[y] = ans[x] + dir; // dir 就是从 x 换到 y 的「变化量」 reroot(y, x, g, ans); } } } }
python3 解法, 执行用时: 628 ms, 内存消耗: 176.6 MB, 提交时间: 2023-09-17 22:33:11
class Solution: def minEdgeReversals(self, n: int, edges: List[List[int]]) -> List[int]: g = [[] for _ in range(n)] for x, y in edges: g[x].append((y, 1)) g[y].append((x, -1)) # 从 y 到 x 需要反向 ans = [0] * n def dfs(x: int, fa: int) -> None: for y, dir in g[x]: if y != fa: ans[0] += dir < 0 dfs(y, x) dfs(0, -1) def reroot(x: int, fa: int) -> None: for y, dir in g[x]: if y != fa: ans[y] = ans[x] + dir # dir 就是从 x 换到 y 的「变化量」 reroot(y, x) reroot(0, -1) return ans