问题描述

给定一个无向、连通的树。树中有 N 个标记为 0...N-1 的节点以及 N-1 条边 。

第 i 条边连接节点 edges[i][0] 和 edges[i][1] 。

返回一个表示节点 i 与其他所有节点距离之和的列表 ans。

示例 1:

输入: N = 6, edges = [[0,1],[0,2],[2,3],[2,4],[2,5]]
输出: [8,12,6,10,10,10]
解释:
如下为给定的树的示意图:
0
/ \
1 2
/|\
3 4 5

我们可以计算出 dist(0,1) + dist(0,2) + dist(0,3) + dist(0,4) + dist(0,5)
也就是 1 + 1 + 2 + 2 + 2 = 8。 因此,answer[0] = 8,以此类推。
说明: 1 <= N <= 10000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sum-of-distances-in-tree

解答

//每个节点到全局的距离,可以由父亲节点到全局的距离推出来
class Solution {
    int[][] fa;
    Map<Integer, List<Integer>> map;
    boolean[] vi;
    int[] result;
    int num;
    public void dfs(int start){
        vi[start] = true;
        List<Integer> temp = map.get(start);
        if(temp.size() == 1 && vi[temp.get(0)])return;
        for(int i:temp){
            if(vi[i])continue;
            dfs(i);
            fa[start][0] += fa[i][0]+1;
            fa[start][1] += fa[i][0]+1 + fa[i][1];
        }
    }
    public void dfs2(int start){
        vi[start] = true;
        List<Integer> temp = map.get(start);
        if(temp.size() == 1 && vi[temp.get(0)])return;
        for(int i:temp){
            if(vi[i])continue;
            //本节点到全局的距离可以由父亲节点到全局的距离推出来
            //全局距离 = 父亲节点到其他节点的距离+外部节点个数+本身作为父节点到全部子节点的距离
            result[i] = (result[start]-(fa[i][0]+fa[i][1]+1))+(num-fa[i][0]-1)+fa[i][1];
            dfs2(i);
        }
    }
    public int[] sumOfDistancesInTree(int N, int[][] edges) {
        result = new int[N];
        vi = new boolean[N];
        if(N<=1)return result;
        map = new HashMap<>();
        num = N;
        for(int[] edge:edges){
            if(!map.containsKey(edge[0]))map.put(edge[0], new ArrayList<Integer>());
            if(!map.containsKey(edge[1]))map.put(edge[1], new ArrayList<Integer>());
            map.get(edge[0]).add(edge[1]);
            map.get(edge[1]).add(edge[0]);
        }

        fa = new int[N][2];
        //0作为起点开始dfs
        dfs(0);
        result[0] = fa[0][1];
        vi = new boolean[N];
        dfs2(0);
        return result;
    }
}