2858. Minimum Edge Reversals So Every Node Is Reachable
There is a simple directed graph with n nodes labeled from 0 to n - 1. The graph would form a tree if its edges were bi-directional.
You are given an integer n and a 2D integer array edges, where edges[i] = [ui, vi] represents a directed edge going from node ui to node vi.
An edge reversal changes the direction of an edge, i.e., a directed edge going from node ui to node vi becomes a directed edge going from node vi to node ui.
For every node i in the range [0, n - 1], your task is to independently calculate the minimum number of edge reversals required so it is possible to reach any other node starting from node i through a sequence of directed edges.
Return an integer array answer, where answer[i] is the minimum* number of edge reversals required so it is possible to reach any other node starting from node i through a sequence of directed edges*.
Example 1:

Input: n = 4, edges = [[2,0],[2,1],[1,3]]
Output: [1,1,0,2]
Explanation: The image above shows the graph formed by the edges.
For node 0: after reversing the edge [2,0], it is possible to reach any other node starting from node 0.
So, answer[0] = 1.
For node 1: after reversing the edge [2,1], it is possible to reach any other node starting from node 1.
So, answer[1] = 1.
For node 2: it is already possible to reach any other node starting from node 2.
So, answer[2] = 0.
For node 3: after reversing the edges [1,3] and [2,1], it is possible to reach any other node starting from node 3.
So, answer[3] = 2.
Example 2:

Input: n = 3, edges = [[1,2],[2,0]]
Output: [2,0,1]
Explanation: The image above shows the graph formed by the edges.
For node 0: after reversing the edges [2,0] and [1,2], it is possible to reach any other node starting from node 0.
So, answer[0] = 2.
For node 1: it is already possible to reach any other node starting from node 1.
So, answer[1] = 0.
For node 2: after reversing the edge [1, 2], it is possible to reach any other node starting from node 2.
So, answer[2] = 1.
Constraints:
2 <= n <= 105edges.length == n - 1edges[i].length == 20 <= ui == edges[i][0] < n0 <= vi == edges[i][1] < nui != vi- The input is generated such that if the edges were bi-directional, the graph would be a tree.
Solution:
本题可以先计算出以 0 为根时的答案:在建图的时候,对于一条 x→y 的边,把 (y,1) 加到 x 的邻居,把 (x,−1) 加到 y 的邻居,从而可以在递归过程中统计有多少条边是需要反向的。
然后换根,假设 y 是 x 的儿子节点,从 x 换根到 y,只会影响 x 和 y 的父子关系,其余节点不受影响,所以
ans[y]=ans[x]+direction 如果从 x 到 y 不需要反向,则换根后需要反向,direction=1,否则等于 −1,这正好就是建图时我们添加的 1 和 −1。
class Solution {
public int[] minEdgeReversals(int n, int[][] edges) {
List<int[]>[] graph = new ArrayList[n];
int[] result = new int[n];
for (int i = 0; i < n; i++){
graph[i] = new ArrayList<>();
}
for (int[] e : edges){
int u = e[0];
int v = e[1];
graph[u].add(new int[]{v, 1}); // correct direction
graph[v].add(new int[]{u, -1}); // reversed direction
}
dfs(0, -1, graph, result);
reroot(0, -1, graph, result);
return result;
}
// compute total reversals starting
private void dfs(int node, int parent, List<int[]>[] graph, int[] result){
for (int[] nei : graph[node]){
int next = nei[0];
int dir = nei[1];
if (next != parent){
if (dir < 0){
result[0]++;
}
dfs(next, node, graph, result);
}
}
}
// reroot DP
private void reroot(int node, int parent, List<int[]>[] graph, int[] result){
for (int[] nei : graph[node]){
int next = nei[0];
int dir = nei[1];
if (next != parent){
result[next] = result[node] + dir;
reroot(next, node, graph, result);
}
}
}
}
// TC: O(n)
// SC: O(n)
re-rooting DP