Given an undirected tree consisting of n vertices numbered from 0 to n-1, which has some apples in their vertices. You spend 1 second to walk over one edge of the tree. Return the minimum time in seconds you have to spend to collect all apples in the tree, starting at vertex 0 and coming back to this vertex.
The edges of the undirected tree are given in the array edges, where edges[i] = [ai, bi] means that exists an edge connecting the vertices ai and bi. Additionally, there is a boolean array hasApple, where hasApple[i] = true means that vertex i has an apple; otherwise, it does not have any apple.
Input: n =7, edges =[[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple =[false,false,true,false,true,true,false]Output: 8Explanation: The figure above represents the given tree where red vertices have an apple. One optimal path to collect all apples is shown by the green arrows.
Input: n =7, edges =[[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple =[false,false,true,false,false,true,false]Output: 6Explanation: The figure above represents the given tree where red vertices have an apple. One optimal path to collect all apples is shown by the green arrows.
Example 3:
1
2
Input: n =7, edges =[[0,1],[0,2],[1,4],[1,5],[2,3],[2,6]], hasApple =[false,false,false,false,false,false,false]Output: 0
The main idea is to use DFS to traverse the tree from the root, only counting the cost to visit subtrees that contain at least one apple. If a subtree (including the current node) has no apples, we skip it. Otherwise, we add 2 seconds for each edge traversed (to go and return), except for the root node, which does not require a return trip.
classSolution {
public: unordered_map<int, vector<int>> g; // to store the graph
unordered_map<int, bool> visited; // to stop exploring same nodes again and again.
voidcreateGraph(vector<vector<int>>& edges) {
for (auto e: edges) {
g[e[0]].push_back(e[1]);
g[e[1]].push_back(e[0]);
}
}
intdfs(int node, int myCost, vector<bool>& hasApple) {
if (visited[node]) {
return0;
}
visited[node] = true;
int childrenCost =0; // cost of traversing all children.
for (auto x: g[node]) {
childrenCost += dfs(x, 2, hasApple); // check recursively for all apples.
}
if (childrenCost ==0&& hasApple[node] == false) {
return0;
}
return (childrenCost + myCost);
}
intminTime(int n, vector<vector<int>>& edges, vector<bool>& hasApple) {
createGraph(edges); // construct the graph first.
return dfs(0, 0, hasApple); // cost of reaching the root is 0. For all others, its 2.
}
};
classSolution {
publicintminTime(int n, int[][] edges, List<Boolean> hasApple) {
Map<Integer, List<Integer>> graph = createGraph(edges); // to store the graph Map<Integer, Boolean> visited =new HashMap<>();
return dfs(graph, 0, hasApple, 0, visited); // cost of reaching the root is 0. For all others, its 2. }
privateintdfs(Map<Integer, List<Integer>> graph, int node, List<Boolean> hasApple, int myCost, Map<Integer, Boolean> visited) {
Boolean v = visited.getOrDefault(node, false);
if (v) {
return 0;
}
visited.put(node, true);
int childrenCost = 0; // cost of traversing all children. for(int n : graph.getOrDefault(node, new ArrayList<>())) {
childrenCost += dfs(graph, n, hasApple, 2, visited); // check recursively for all apples in subtrees. }
if (childrenCost == 0 && hasApple.get(node) ==false) {
// If no child has apples, then we won't traverse the subtree, so cost will be zero.// similarly, if current node also does not have the apple, we won't traverse this branch at all, so cost will be zero.return 0;
}
return childrenCost + myCost;
}
private Map<Integer, List<Integer>>createGraph(int[][] edges) {
Map<Integer, List<Integer>> graph =new HashMap<>();
for(int i = 0; i < edges.length; i++) {
List<Integer> list = graph.getOrDefault(edges[i][0], new ArrayList<>()); // Adjecency list representation. list.add(edges[i][1]);
graph.put(edges[i][0], list);
list = graph.getOrDefault(edges[i][1], new ArrayList<>()); // Adjecency list representation. list.add(edges[i][0]);
graph.put(edges[i][1], list);
}
return graph;
}
}