JAVA SOLUTION
Intuition\n\n Describe your first thoughts on how to solve this problem. \n\n# Approach\n Describe your approach to solving the problem. \n\n# Complexity\n- Tim
# Intuition\n![images.jfif](https://assets.leetcode.com/users/images/2a46905d-e3ed-49ac-84d1-a846842c0264_1720419932.952098.jpeg)\n<!-- Describe your first thoughts on how to solve this problem. -->\n\n# Approach\n<!-- Describe your approach to solving the problem. -->\n\n# Complexity\n- Time complexity:\n<!-- Add your time complexity here, e.g. $$O(n)$$ -->\n\n- Space complexity:\n<!-- Add your space complexity here, e.g. $$O(n)$$ -->\n\n# Code\n```\nclass Solution {\n\n    List<Integer>[] tree, subTree;\n    int subTreeRoot, maxPath;\n    boolean[] inStack; // do not allow to travel upwards in the rooted tree\n    int[] ans;\n\n    public int[] countSubgraphsForEachDiameter(int n, int[][] edges) {\n        buildTree(n, edges);\n        ans = new int[n - 1];\n        solve(0);\n        return ans;\n    }\n\n    private void buildTree(int n, int[][] edges) {\n        tree = new List[n];\n        subTree = new List[n];\n        inStack = new boolean[n];\n        for (int i = 0; i < n; ++i) {\n            tree[i] = new ArrayList<>();\n            subTree[i] = new ArrayList<>();\n        }\n        for (int[] e : edges) {\n            tree[e[0] - 1].add(e[1] - 1);\n            tree[e[1] - 1].add(e[0] - 1);\n        }\n    }\n\n    private void solve(int i) {\n        subTreeRoot = i;\n        inStack[i] = true;\n        buildSubTree(0, 0, Collections.singletonList(i), new ArrayList<>());\n        for (int e : tree[i]) {\n            if (inStack[e]) {\n                continue;\n            }\n            solve(e);\n        }\n    }\n\n    private void buildSubTree(int i, int j, List<Integer> fronteer, List<Integer> next) {\n        if (i >= fronteer.size()) {\n            buildNextLevel(next);\n            return;\n        }\n        int curr = fronteer.get(i);\n        if (j >= tree[curr].size()) {\n            buildSubTree(i + 1, 0, fronteer, next);\n        } else {\n            int succ = tree[curr].get(j);\n            if (inStack[succ]) {\n                buildSubTree(i, j + 1, fronteer, next);\n                return;\n            }\n            inStack[succ] = true;\n            next.add(succ);\n            subTree[curr].add(succ);\n            buildSubTree(i, j + 1, fronteer, next);\n            next.remove(next.size() - 1);\n            subTree[curr].remove(subTree[curr].size() - 1);\n            buildSubTree(i, j + 1, fronteer, next);\n            inStack[succ] = false;\n        }\n    }\n\n    private void buildNextLevel(List<Integer> next) {\n        if (next.isEmpty()) { // subTree is done, add it to the answer\n            maxPath = 0;\n            computeMaxPath(subTreeRoot);\n            if (maxPath > 1) {\n                ++ans[maxPath - 2];\n            }\n        } else {\n            buildSubTree(0, 0, next, new ArrayList<>());\n        }\n    }\n\n    private int computeMaxPath(int i) {\n        int max = 0, prevMax = 0;\n        for (int child : subTree[i]) {\n            int h = computeMaxPath(child);\n            if (h >= max) {\n                prevMax = max;\n                max = h;\n            } else {\n                prevMax = Integer.max(prevMax, h);\n            }\n        }\n        maxPath = Integer.max(maxPath, prevMax + max + 1);\n        return max + 1;\n    }\n}\n```
['Java']