动态规划--树形DP之换根DP

class Solution {
    private List<Integer>[] g;
    private int[] ans,size;
    public int[] sumOfDistancesInTree(int n, int[][] edges) {
        ans = new int[n];
        size = new int[n];
        g = new ArrayList[n];
        //Arrays.setAll(g,e -> new ArrayList<>());
        for(int i = 0;i < n;i++){ //首先定义的是一个List一维数组 然后再分别在每一个数组中g[i] 再建立List数组
            g[i] = new ArrayList<>();
        }
        for(var e : edges){ //将相连的边加上
            int x = e[0], y = e[1]; //此处居然不可以省 只能写个临时变量填进去!!!!好奇怪的
            g[x].add(y);
            g[y].add(x);
        }
        dfs(0,-1,0);//0没有父节点
        reroot(0,-1);
        return ans;
    }
    //dp总得初始化吧 这样别的点才可以由此推导出来 此处函数就是初始化ans[0]->从0开始dfs,累加0到每个点的距离  
    //同时计算每棵子树size[i] 以便换根计算
    private void dfs(int root,int fa,int depth){ //此处的root为递归到某个节点将其看做临时的根节点 但是fa又是递归到她的父节点
        //由于采用递归所以depth即为深度 ans刚好就加上每个节点的depth就表示与0的距离了 递归到每个节点 就可以都加上
        ans[0] += depth;//累加0到每个节点的距离 即完成ans[0]的初始化
        size[root] = 1;//每个节点所包含的子树 包括自己;初始化就为1
        for(int neigh : g[root]){
            if(neigh != fa){ //此处避免递归到父节点
                dfs(neigh,root,depth+1);
                size[root] += size[neigh];//注意递归我是直接谈到底部 返回的时候才会进行计算返回值 
            }
        }
    }
    private void reroot(int root,int fa){
        for(int neigh : g[root]){
            if(neigh != fa){
                ans[neigh] += ans[root] + g.length - 2 * size[neigh];
                reroot(neigh,root);
            }
        }
    }
}
/*
基本思路:主函数中 dfs暴搜每个点并标记已搜过的点,在暴搜每个点时调用dfs函数()
dfs()函数基本思路也是暴搜加上数组值()也就是距离 然后返回长度和。   没看懂题胡诌!!!

 ans[i] 节点i与其他所有节点距离之和
 size[i]表示节点i下属的子树包含的子节点的个数 也包含自身
 */

猜你喜欢

转载自blog.csdn.net/m0_61843855/article/details/131757080
今日推荐