列表

详情


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 。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: vector<int> minEdgeReversals(int n, vector<vector<int>>& edges) { } };

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

上一题