[C++][C#][Java][Javascript] simple map solution, no recursion, bottom-up
If there\'s an apple for number - travel from the node with apple to the root. So we need a map - child to parent.\nDo not travel same path again - mark as -1 i
If there\'s an apple for number - travel from the node with apple to the root. So we need a map - child to parent.\nDo not travel same path again - mark as `-1` in the map.\n\n**[update] Since they updated test cases and no longer guarantee that edges are sorted, we need to do sorting first, which makes complexity O(NlogN) instead of O(N) Anyways I think it\'s good to know that there\'re other ways to solve the problem when certain preconditions\'re met.**\n\n*Note: this solution is good for when there\'s no guarantee that edges are "sorted" by level. It looks like they are sorted, so there\'s event simpler solution by traversing edges from end to start and propogating apples to parents.*\n\nC++\n```\nint minTime(int n, vector<vector<int>>& edges, vector<bool>& hasApple) {\n    unordered_map<int, int> m;\n\tstd::sort(edges.begin(), edges.end());\n   for(auto const& edge : edges)  {\n        if (m.count(edge[1]) > 0) m[edge[0]] = edge[1];\n        else m[edge[1]] = edge[0];\n    }\n    int result = 0;\n    for(int i = 0; i < hasApple.size(); ++i) {\n        if (!hasApple[i]) continue;\n        int parent = i;\n        while(parent != 0 && m[parent] >= 0) {\n            auto temp = m[parent];\n            m[parent] = -1;\n            parent = temp;\n            result += 2;\n        }\n    }\n    return result;\n}\n```\n\n\nC#\n```\npublic int MinTime(int n, int[][] edges, IList<bool> hasApple) {\n    var m = new Dictionary<int, int>();\n\tedges = edges.OrderBy(x => x[0]).ToArray(); // sort if needed, input used to be sorted\n    foreach(var edge in edges)\n        if (m.ContainsKey(edge[1]))\n            m[edge[0]] = edge[1];\n        else \n            m[edge[1]] = edge[0];\n\n    var result = 0;\n    for(var i = 0; i < hasApple.Count; ++i) {\n        if (!hasApple[i]) continue;\n        var p = i;\n        while(p != 0 && m[p] >= 0) {\n            var temp = m[p];\n            m[p] = -1; // mark as visited\n            p = temp;\n            result += 2;\n        }\n    }\n    return result;\n}\n```\n\nJava\n```\npublic int minTime(int n, int[][] edges, List<Boolean> hasApple) {\n    HashMap<Integer, Integer> m = new HashMap<Integer, Integer>();\n\tjava.util.Arrays.sort(edges, new java.util.Comparator<int[]>() {\n        public int compare(int[] a, int[] b) {\n            return a[0] - b[0];\n        }\n    });\n    for(int[] edge: edges)\n\t\tif (m.containsKey(edge[1]))\n            m.put(edge[0], edge[1]);\n        else\n            m.put(edge[1], edge[0]);\n\n    int result = 0;\n    for(int i = 0; i < hasApple.size(); ++i) {\n        if (!hasApple.get(i)) continue;\n        int p = i;\n        while(p != 0 && m.get(p) >= 0) {\n            int temp = m.get(p);\n            m.put(p, -1); // mark as visited\n            p = temp;\n            result += 2;\n        }\n    }\n    return result;\n}\n```\n\nJavascript\n```\nvar minTime = function(n, edges, hasApple) {\n    const m = {};\n\tedges.sort((a,b) => a[0] - b[0]);\n    for(let edge of edges) \n        if (m[edge[1]] !== undefined)\n            m[edge[0]] = edge[1];\n        else\n            m[edge[1]] = edge[0];\n\n    let result = 0;\n    for(let i = 0; i < hasApple.length; ++i) {\n        if (!hasApple[i]) continue;\n        let p = i;\n        while(p != 0 && m[p] >= 0) {\n            const temp = m[p];\n            m[p] = -1; // mark as visited\n            p = temp;\n            result += 2;\n        }\n    }\n    return result;\n};\n```
['C++', 'Java', 'JavaScript', 'C#']