Python backtracking with edges than nodes O(n*2^n)
The key thing is, instead of determining which nodes to construct the subtree, use edges.\n\n1. Backtrack to find all subtree candidates\n\t1.1 for each candida
The key thing is, instead of determining which nodes to construct the subtree, use edges.\n\n1. Backtrack to find all subtree candidates\n\t1.1 for each candidate determine if it is a tree\n\t1.2 calculate the diameter of such tree\n\nTime complexcity is 14 * 2 ^ 14\uFF1B\n```\nclass Solution:\n    \n    def isTree(self, edges):\n        \n        graph = collections.defaultdict(set)\n        matching = {}\n        curIdx = 0\n        for edge in edges:\n            l, r = edge[0], edge[1]\n            if l not in matching:\n                matching[l] = curIdx\n                curIdx += 1\n            if r not in matching:\n                matching[r] = curIdx\n                curIdx += 1\n            graph[matching[l]].add(matching[r])\n            graph[matching[r]].add(matching[l])\n        \n        seen = [0] * curIdx\n\n        def dfs(i):\n            if seen[i]: return 0\n            seen[i] = 1\n            for j in graph[i]: dfs(j)\n            return 1\n\n        return sum(dfs(i) for i in range(curIdx)) - 1 == 0\n        \n    \n    def getDofTree(self, edges, graph):\n        graph = collections.defaultdict(set)\n        matching = {}\n        curIdx = 0\n        for edge in edges:\n            l, r = edge[0], edge[1]\n            if l not in matching:\n                matching[l] = curIdx\n                curIdx += 1\n            if r not in matching:\n                matching[r] = curIdx\n                curIdx += 1\n            graph[matching[l]].add(matching[r])\n            graph[matching[r]].add(matching[l])\n        \n        n = curIdx\n        #print(graph)\n        res = 0\n        \n        def getL(node, graph, parent):\n            nonlocal res\n            nonlocal n\n            if not graph[node]:\n                return 1\n            hq = []\n            for child in graph[node]:\n                #print(child)\n                if child == parent:\n                    continue\n                heapq.heappush(hq, getL(child, graph, node))\n                if len(hq) > 2:\n                    heapq.heappop(hq)\n            res = max(res, sum(hq))\n            if hq:\n                return hq[-1] + 1\n            else:\n                return 1\n            \n        getL(0, graph, -1)\n        return res\n\n    \n    def countSubgraphsForEachDiameter(self, n: int, edges: List[List[int]]) -> List[int]:\n        \n        res = [0 for _ in range(n)]\n        maxGraph = collections.defaultdict(set)\n        possiblePath = set()\n        \n        for edge in edges:\n            maxGraph[edge[0]].add(edge[1])\n            maxGraph[edge[1]].add(edge[0])\n            #possiblePath.add((min(edge[0], edge[1]), max(edge[0], edge[1])))\n        \n        def bt(cur, curEdges, edges):\n            if cur == n - 1:        \n                if len(curEdges) >= 1:\n                    if self.isTree(curEdges):\n                        res[self.getDofTree(curEdges, maxGraph)] += 1                \n                return\n            bt(cur + 1, curEdges + [edges[cur]], edges)\n            bt(cur + 1, curEdges, edges)\n            \n        bt(0, [], edges)\n        return res[1:]\n    \n```
[]